How do find the granchild pid in C? - c

I am trying to code a toy process manager and was wondering how do I find the grandchild pids when one of my children pids dies. I.e. how to deal with the "Readiness protocol".
systemd has the "Type=forking" option, which as far as I understand, waits for the forked pid to die and then assumes that one of the forked pid's children is the actual "daemon" to monitor.
My code so far is as following, but I am missing the XXX
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/prctl.h>
int
main (int argc, const char *argv[])
{
printf("sup stared\n");
int pid;
prctl(PR_SET_CHILD_SUBREAPER);
pid = fork();
if (pid == 0) {
setpgid(0, 0);
printf("service started, pid: %d, pgid: %d\n",
getpid(), getpgid(0));
int dpid;
dpid = fork();
if (dpid == 0) {
printf("daemon started, pid: %d, pgid: %d\n",
getpid(), getpgid(0));
while (1);
}
printf("service exiting\n");
return 0;
} else {
printf("service pid: %d\n", pid);
int rc;
rc = waitpid(pid, NULL, 0);
printf("service exited? %d\n", rc);
int dpid;
dpid = XXcX();
printf("daemon, %d\n", dpid);
}
return 0;
}

Related

Access shared memory to child process with signal

I need some help with my c program. Basically, in my c program, I wish my parent process calculates a+b and my child process calculates 3*(a+b). However, I don't how to access the shared memory after sending the signal. Any help is appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
void sigcont(int shmid);
int main (int argc, char *argv[]){
int shmid;
int *result;
pid_t pid;
int size_data = 2 * sizeof (int);
shmid = shmget (IPC_PRIVATE, size_data, 0666 | IPC_CREAT);
pid = fork ();
if (pid == 0) {
signal(SIGCONT, sigcont);
while (1);
}
else {
sleep(1);
result = (int *) shmat (shmid, NULL, 0);
result[0] = atoi (argv[2]) + atoi (argv[1]);
printf ("Result in parent process %d: %d.\n", getpid() , result[0]);
printf ("Send a SIGCONT to process %d.\n\n", pid);
shmdt (result);
kill (pid, SIGCONT);
wait(NULL);
printf ("\nThis is the End.\n");
}
return 0;
}
void sigcont(int shmid){
printf("Get a SIGCONT.\n");
printf("Result in child process ID: %d.\n", getpid());
exit(0);
}
What I have tried:
Put one parameter in void sigcont(int shmid);
As I am learning from https://www.geeksforgeeks.org/signals-c-set-2/. Do signal() and kill() must use in pair? I get Thus, I tried to pass a value to it. Not working.
Sigstop() and Sigcont()
I tried to avoid using signal() in my child process so that I can access shmid directly. But I couldn't find a lot of examples of Sigstop() and Sigcont(). It fails as well.
It's really hard to get my desired result even it looks simple. Can anyone help with this? Any help is appreciated.
Notes: added error checking; call shmat() and save to global before fork(), child to inherit attached shared mem; SIGCONT better for stopped process, selected SIGUSR1; arg to sig handler is signal #; child was spinning, for minimal overhead better to pause().
This version is an example, and does not attempt to support every system imagined.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int *shmloc;
void shandler(int sig)
{
printf("pid %d, sig %d\n", getpid(), sig);
printf("mult result: %d\n", *shmloc * 3);
}
int main(int argc, char *argv[])
{
int a, b, shmid, size_data, sig;
pid_t pid;
if (argc < 3) {
fprintf(stderr, "missing args a b\n");
return (1);
}
// OP: shmget() size arg, some systems may require a minimum, may roundup
size_data = 2 * sizeof (int);
shmid = shmget(IPC_PRIVATE, size_data, 0666 | IPC_CREAT);
if (shmid == -1) {
fprintf(stderr, "shmget failed, %s\n", strerror(errno));
return (1);
}
shmloc = shmat(shmid, NULL, 0);
if (shmloc == (void *) -1) {
fprintf(stderr, "shmat failed, %s\n", strerror(errno));
return (1);
}
sig = SIGUSR1;
pid = fork();
if (pid < 0) {
fprintf(stderr, "fork failed, %s\n", strerror(errno));
return (1);
}
// child only
if (pid == 0) {
signal(sig, shandler);
pause();
printf("child exit\n");
_exit(0);
}
sleep(1);
// OP: care about non-digits in cmd-line args?
a = atoi(argv[1]);
b = atoi(argv[2]);
*shmloc = a + b;
printf("parent pid %d, add (%d, %d) result %d\n", getpid(), a, b, *shmloc);
shmdt(shmloc);
printf("sending signal %d to child %d\n", sig, pid);
kill(pid, sig);
wait(NULL);
printf("\nThis is the End.\n");
return (0);
}

How to make parent process wait for child processes to finish?

I have an assignment which gives me this code to transform into a code that makes the parent process wait for all children processes to finish.
PS: the first code has 4 processes and needs to use waitpid to solve this.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main(){
pid_t p = fork();
pid_t k = fork();
if(p>0){
printf("p=%d: PID = %d\n", p, getpid());
sleep(45);
exit(0);
}
else if(p==0){
printf("p=%d: PID = %d\n", p, getpid());
exit(0);
}
else if(p<0){
printf("ERRO! p=%d\n", p);
exit(p);
}
}
I've tried this, but I think that this only works for only 1 child process and not for a lot of them.
int main(){
pid_t p = fork();
pid_t k = fork();
if(p<0){
printf("fodeu");
exit(p);
}
else if(p==0){
printf("");
exit(0);
}
else{
for(i=0;i<4;i++){
int returnstatus;
waitpid(p,&returnstatus,0);
if(returnstatus == 0){
printf("o processo filho correu normalmente");
}
else if(returnstatus == 1){
printf("o processo filho ardeu");
}
}
}
}
This won't do your assignment, but I hope it is advice enough to get
you going. The assignment appear to be a riddle around fork(), your
teacher has good taste :-)
fork() is different. It returns twice.
In the parent it returns the process ID of the created process.
In the child it returns 0; a process can always determine its PID using getpid()
Actually, the assignment is not good taste. Usually code using `fork()
never lets any branch escape into enclosing code to avoid complete
bullshit. Like so,
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
pid_t pid = fork();
if (pid == 0 /*child*/) {
printf("PID %d (child) doing work\n", pid);
sleep(5);
exit(0); // don't let it continue (leak) into parent code
}
else if (pid > 0 /*parent*/) {
int status;
pid_t terminated;
printf("PID %d (parent) waiting for child PID %d\n", getpid(), pid);
terminated = waitpid(pid, &status, 0);
if (terminated == -1) {
perror("waitpid");
exit(1);
}
if (WIFEXITED(status))
printf("child exited normally with status %d\n", WEXITSTATUS(status));
else
printf("hm. child died otherwise. see 'man waidpid' for more\n");
}
return 0;
}
With this in mind, look at these two innocent looking lines,
pid_t p = fork(); // two processes after this
pid_t k = fork(); // executed by **two** processes, again duplicating
So, after these two lines we have four processes executing the rest of
the code in parallel. This is the point where brains explode. What
does the leaked child of the k line do when it asks what p's value
is?
Look at the output of this little program, to see what's the effect of
leaking.
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main(){
printf("MAIN PID %d\n", getpid());
fork();
fork();
printf("PID %d, PPID %d\n", getpid(), getppid());
return 0;
}
This is one way to do it; there will be numerous others.
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
static void wait_for_kids(void);
int main(void)
{
pid_t p = fork();
pid_t k = fork();
if (p > 0)
{
printf("p=%d: PID = %d\n", p, getpid());
sleep(5);
wait_for_kids();
printf("%d: p = %5d, k = %5d - exiting\n", getpid(), p, k);
exit(0);
}
else if (p == 0)
{
printf("p=%d: PID = %d\n", p, getpid());
wait_for_kids();
printf("%d: p = %5d, k = %5d - exiting\n", getpid(), p, k);
exit(0);
}
else
{
printf("ERROR! p=%d\n", p);
wait_for_kids();
printf("%d: p = %5d, k = %5d - exiting\n", getpid(), p, k);
exit(p);
}
/*NOTREACHED*/
}
static void wait_for_kids(void)
{
int corpse;
int status;
int pid = getpid();
while ((corpse = waitpid(0, &status, 0)) > 0)
printf("%d: child %d exited with status 0x%.4X\n", pid, corpse, status);
}
Example output:
p=43445: PID = 43444
p=43445: PID = 43446
p=0: PID = 43445
p=0: PID = 43447
43447: p = 0, k = 0 - exiting
43445: child 43447 exited with status 0x0000
43445: p = 0, k = 43447 - exiting
43446: p = 43445, k = 0 - exiting
43444: child 43445 exited with status 0x0000
43444: child 43446 exited with status 0x0000
43444: p = 43445, k = 43446 - exiting

Fork and exec several children in linux

I want to fork and exec several processes from another.
My parent code is
/*Daddy.c*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main(void)
{
int status;
char *nChild;
for (int i=0; i<3;i++){
int pid = fork();
if (pid == 0)
{
sprintf(nChild, "%d", i);
printf("%d\n", i);
char *const arguments[]={nChild, NULL};
fflush(NULL);
execv("child",arguments);
printf("\nNo , you can't print!\n");
}else if (pid == -1){
printf("%d\n", getpid());
exit(0);
}
}
wait(&status);
printf("Dad %d went out!\n", getpid());
exit(0);
}
and my child process is
/*child.c*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int args, char **argv){
if( args !=2){
printf("Child going away!\n");
exit(1);
}
printf("Child %s: %d going away stylishly!\n", argv[1], getpid());
exit(0);
}
When I don´t create three forks, but one, I know how to create the child, do some work and exit from child and parent. But, in this case, with several children it seems like the child never executes.
Because of the line wait(&status) I did hope that when the first child exits, the parent also exits but, any child prints any message.
Some relevant previous questions didn´t help.
You need to make parent wait for all child processes to finish. If not, assume that 1 child waited for is done and then parent exits. What about the other 2 children? They become orphan since their parent doesn't wait for them.
pid_t wpid;
int status = 0;
.
.
while ((wpid = wait(&status)) > 0); // the parent waits for all the child processes
This code did the job
/* daddy.c */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
int main(void)
{
int status=0;
char nChild[16];
pid_t wpid;
for (int i=0; i<3;i++){
sprintf(nChild, "%d", i);
int pid = fork();
if (pid == 0)
{
printf("%s\n", nChild);
char *const arguments[]={"child", nChild, NULL};
fflush(NULL);
execv("child",arguments);
printf("\nNo , you can't print!\n");
}else if (pid == -1){
printf("%d\n", getpid());
exit(0);
}
}
while ((wpid=wait(&status)) >0);
printf("Dad %d went out!\n", getpid());
exit(0);
}
As #OnzOg said in the comments of the question, allocation of nChild was the main problem. Also execv need pass child name twice, one as argument.
And finally, to improve the code, parent process needs to wait all processes to finish.

Set fork()'s child into foreground, and exit parent

I am trying to change the PID of a process in Linux.
Then the idea is to use fork() to spawn a child, and give the control of the terminal to this child, then exit from parent.
The result would be a new process with new process PID without interrupting the execution flow.
I've coded the following PoC, but it doesn't work. If I don't use wait() on the parent, the child process doesn't take control of the terminal. I mean, it continues outputting but the stdin is not attached to the child, is owned by bash.
#include <string.h>
#include <stdio.h>
#include <asm/ptrace.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/sched.h>
#include <stdlib.h>
#include <signal.h>
int main(void) {
int i = 0, ret = 0;
pid_t pid = 0;
printf("PID = %d\n", getpid());
pid = fork();
if (pid == -1) {
return -1;
}
if (pid != 0) {
printf("Parent PGID = %d\n", getpgid(0));
printf("Parent PGID for 0 = %d\n", tcgetpgrp(0));
signal(SIGTTOU, SIG_IGN);
for (i = 0; i < 3; i++) {
ret = tcsetpgrp(i, pid);
}
exit(0);
}
setpgid(0, 0);
printf("Child PGID = %d\n", getpgid(0));
printf("Child PGID for 0 = %d\n", tcgetpgrp(0));
for (i = 0; 1; i++) {
printf("iter = %d, PID = %d\n", i, getpid());
usleep(300000);
}
return 0;
}
Thanks in advance.

How run a program in C for x minutes?

I am trying to run a program in C for x minutes. I need to make the child process go to sleep for that amount of time. Any help would be appreciated. Basically I am trying to understand how fork() and sleep() work. Here is my code snippet
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int i = fork();
printf("fork return value = %d\n", i);
printf("this is the time before sleep");
system("date +%a%b%d-%H:%M:%S");
printf("\n");
if (i==0){
sleep(120);
}
system("ps");
printf("this is the time after sleep");
system("date +%a%b%d-%H:%M:%S");
printf("\n");
}
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(void)
{
pid_t pid;
int rv=1;
switch(pid = fork()) {
case -1:
perror("fork"); /* something went wrong */
exit(1); /* parent exits */
case 0:
printf(" CHILD: This is the child process!\n");
printf(" CHILD: My PID is %d\n", getpid());
printf(" CHILD: My parent's PID is %d\n", getppid());
printf(" CHILD: I'm going to wait for 30 seconds \n");
sleep(30);
printf(" CHILD: I'm outta here!\n");
exit(rv);
default:
printf("PARENT: This is the parent process!\n");
printf("PARENT: My PID is %d\n", getpid());
printf("PARENT: My child's PID is %d\n", pid);
printf("PARENT: I'm now waiting for my child to exit()...\n");
wait(&rv);
printf("PARENT: I'm outta here!\n");
}
return 0;
}
Say thanks to Brian "Beej Jorgensen" Hall

Resources