/* * This file is part of Jehanne. * * Copyright (C) 2017 Giacomo Tesio * * This is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, version 3 of the License. * * Jehanne is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Jehanne. If not, see . */ #include #include int r1; int r2; #define CHILD_READY(pid) ((long)rendezvous(&r1, (void*)(~(pid)))) //#define C2P_READY(pid) ((long)rendezvous(&r2, (void*)(~(pid)))) int *__target_pid; static void forwarding_note_handler(void *ureg, char *note) { postnote(PNPROC, *__target_pid, note); noted(NDFLT); } static void donothing(void) { int i = 0; while(++i < 100) sleep(3000); exits(nil); } static int crazy_fork(void) { int father = getpid(); int p2c; long c2p = -1, child = -1; switch(p2c = rfork(RFPROC|RFMEM)){ case -1: return -1; case 0: switch(c2p = rfork(RFPROC|RFMEM)){ case -1: exits("rfork (c2p)"); case 0: switch(child = fork()){ case -1: exits("rfork (child)"); case 0: return 0; default: while(CHILD_READY(child) == -1) ; *__target_pid = father; notify(forwarding_note_handler); donothing(); } default: while((child = CHILD_READY(-3)) == -1) ; child = ~child; *__target_pid = child; notify(forwarding_note_handler); donothing(); } default: break; } return p2c; } int pass_on_die(void *v, char *s) { if(strncmp(s, "die", 4) == 0){ print("PASS\n"); exits("PASS"); } return 0; } void main(void) { int c, target_pid = 0; __target_pid = &target_pid; if (!atnotify(pass_on_die, 1)){ fprint(2, "%r\n"); exits("atnotify fails"); } c = crazy_fork(); switch(c){ case -1: print("FAIL: fork\n"); exits("FAIL"); case 0: print("child is %d; child's parent is %d\n", getpid(), getppid()); *__target_pid = getppid(); notify(forwarding_note_handler); /* wait to be killed */ donothing(); break; default: print("father is %d; forked child is %d\n", getpid(), c); sleep(1000); /* give children time to notify() */ print("starting note chain\n"); postnote(PNPROC, c, "die"); /* wait to be killed by the chain */ sleep(30000); } print("FAIL\n"); exits("FAIL"); }