Skip to content

Instantly share code, notes, and snippets.

@Martiusweb
Created August 9, 2018 20:35
Show Gist options
  • Save Martiusweb/cdeb27593bf96c891c054db0ddb0c5f1 to your computer and use it in GitHub Desktop.
Save Martiusweb/cdeb27593bf96c891c054db0ddb0c5f1 to your computer and use it in GitHub Desktop.
TLPI 26-2
#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