doublefork.c (1081B)
1 /* ISC license. */ 2 3 #include <sys/wait.h> 4 #include <unistd.h> 5 #include <errno.h> 6 7 #include <skalibs/uint64.h> 8 #include <skalibs/allreadwrite.h> 9 #include <skalibs/djbunix.h> 10 #include <skalibs/posixplz.h> 11 12 pid_t doublefork () 13 { 14 char pack[8] ; 15 int fd[2] ; 16 pid_t child ; 17 if (pipe(fd) == -1) return -1 ; 18 child = fork() ; 19 switch (child) 20 { 21 case -1: 22 { 23 fd_close(fd[1]) ; 24 fd_close(fd[0]) ; 25 return -1 ; 26 } 27 case 0: 28 { 29 pid_t pid ; 30 fd_close(fd[0]) ; 31 pid = fork() ; 32 switch (pid) 33 { 34 case -1: _exit(errno) ; 35 case 0: fd_close(fd[1]) ; return 0 ; 36 } 37 uint64_pack_big(pack, pid) ; 38 _exit((allwrite(fd[1], pack, 8) < 8) ? errno : 0) ; 39 } 40 } 41 fd_close(fd[1]) ; 42 { 43 uint64_t grandchild = 0 ; 44 int wstat ; 45 if (allread(fd[0], pack, 8) < 8) grandchild = 1 ; 46 fd_close(fd[0]) ; 47 wait_pid(child, &wstat) ; 48 if (grandchild) return (errno = WIFSIGNALED(wstat) ? EINTR : WEXITSTATUS(wstat), -1) ; 49 uint64_unpack_big(pack, &grandchild) ; 50 return (pid_t)grandchild ; 51 } 52 }