Created
August 9, 2018 20:35
-
-
Save Martiusweb/cdeb27593bf96c891c054db0ddb0c5f1 to your computer and use it in GitHub Desktop.
TLPI 26-2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <signal.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <string.h> | |
#include <errno.h> | |
/** | |
* assuming grand parent, parent and child: | |
* | |
* * a.out shows that as soon as "parent" is a zombie, child is orphaned and | |
* adopted by pid 1. | |
* * a.out zombies shows that since child is adopted, it doesn't stay a zombie, | |
* even if parent is. | |
*/ | |
int main(int argc, char* argv[]) { | |
int terminate_child = 0; | |
setvbuf(stdout, NULL, _IONBF, 0); | |
setvbuf(stderr, NULL, _IONBF, 0); | |
if(argc > 1) { | |
if(strcmp(argv[1], "zombies") == 0) { | |
printf("Will terminate child promptly (to verify if it stays a zombie\n"); | |
terminate_child = 1; | |
} | |
} | |
// block SIGCHLD, we'll never await anyone (this is inherited by children) | |
sigset_t blocked; | |
sigemptyset(&blocked); | |
sigaddset(&blocked, SIGCHLD); | |
sigprocmask(SIG_BLOCK, &blocked, NULL); | |
printf("Welcome, i'm grand father (pid: %ld)\n", (long) getpid()); | |
pid_t parent = fork(); | |
if(parent == 0) { | |
int pipefd[2]; | |
if(pipe(pipefd) == -1) { | |
perror("Could not create pipe in parent, killing grand-parent and terminating self"); | |
kill(getppid(), SIGTERM); | |
exit(0); | |
} | |
pid_t child = fork(); | |
if(child == 0) { | |
printf("I'm child (pid: %ld)\n", (long) getpid()); | |
close(pipefd[1]); | |
if(read(pipefd[0], NULL, 0) == 0) { | |
sleep(1); /* pipe can be closed before the process actually | |
exited, this "ensures" that the parent is a zombie | |
alternatively reading /proc can help*/ | |
printf("parent terminated! PPID is now %ld\n", (long) getppid()); | |
} | |
else { | |
// Assume we never read a byte, it's -1 | |
perror("Could not read on pipe"); | |
} | |
close(pipefd[0]); | |
if(terminate_child) { | |
printf("Terminating child\n"); | |
exit(0); | |
} | |
else { | |
printf("Keeping child alive\n"); | |
pause(); | |
} | |
} | |
else { | |
close(pipefd[0]); | |
printf("I'm parent (pid: %ld)\n", (long) getpid()); | |
printf("parent going to terminate, now that child exists\n"); | |
exit(0); // this will close the write side of the pipe, thus notifying the child that we're dead. | |
} | |
} | |
else { | |
printf("Grand father awaiting forever\n"); | |
pause(); | |
} | |
exit(0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment