chris@umcp-cs.UUCP (01/16/84)
Something that network servers often do is while ((netfd = netopen ()) >= 0) { if ((pid = fork ()) == 0) { if (fork ()) exit (0); workhorse (); exit (0); } close (netfd); } The purpose of the double-fork is to "disown" the actual worker and let the server continue to accept network connections. Without the "disownment", when the "workhorse" finishes and exit()s, it hangs around forever taking up a process slot, just so that it can return its status to its parent. But the server doesn't care, ergo the double-fork-be- inherited-by-init trick. So, my suggestion is a "disown" system call, to allow parents to give up their children so that on exit they will vanish without a trace. Does anyone know why this should not be implemented (other than because you can do it without this)? Alternatively, does anyone have better ideas? -- In-Real-Life: Chris Torek, Univ of MD Comp Sci UUCP: {seismo,allegra,brl-bmd}!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris.umcp-cs@CSNet-Relay
guy@rlgvax.UUCP (Guy Harris) (01/16/84)
If it shouldn't be implemented, USG UNIX is in trouble - from SIGNAL(2), UNIX 3.0 User's Manual: ...SIGCLD 18 (not reset when caught) ...SIG_IGN - ignore signal The signal is to be ignored. Also, if 'sig' is SIGCLD, the calling process's (shouldn't that be process'? -gh) child processes will not create zombie processes when they terminate; see exit(2). So signal(SIGCLD, SIG_IGN) will disown all child processes that exit while SIGCLD is being ignored. The signal SIGCLD is delivered whenever a child process exits; this is sort of like the SIGCHLD in the Berkeley job control code, which is delivered whenever the state of a child process child changes - this includes exits, and also includes stopping, etc.. I remember reading some code, I think in the C shell, which does signal(SIGCHLD, SIG_IGN) From what I could see, the kernel does the same thing whether the action for SIGCHLD is SIG_DFL or SIG_IGN; i.e., the default action for SIGCHLD is to do nothing. The same is the case with the USG SIGCLD (i.e., if you don't catch it, it's as if you ignored it except that zombies are created). Is there any difference between 4.xBSD's handling of SIGCHLD if the action is SIG_IGN or SIG_DFL? And, if not, and if all cases where SIGCHLD was ignored the code were changed to reset it to SIG_DFL, could the SIGCLD and SIGCHLD signals be combined? (The S3 manual says that SIGCLD is included only for compatibility with "other versions of UNIX", and is not guaranteed to behave the same in future releases of UNIX; it's "use in new programs is strongly discouraged." However, that signal still appears in System V, albeit with the same caveat, and the S5 "init" uses it.) Guy Harris {seismo,ihnp4,allegra}!rlgvax!guy
jsq@ut-sally.UUCP (John Quarterman) (01/16/84)
x From: chris@umcp-cs.UUCP Subject: New? idea Message-ID: <4771@umcp-cs.UUCP> Date: Sun, 15-Jan-84 17:43:17 CST Something that network servers often do is while ((netfd = netopen ()) >= 0) { if ((pid = fork ()) == 0) { if (fork ()) exit (0); workhorse (); exit (0); } close (netfd); } The purpose of the double-fork is to "disown" the actual worker and let the server continue to accept network connections. Without the "disownment", when the "workhorse" finishes and exit()s, it hangs around forever taking up a process slot, just so that it can return its status to its parent. But the server doesn't care, ergo the double-fork-be- inherited-by-init trick. So, my suggestion is a "disown" system call, to allow parents to give up their children so that on exit they will vanish without a trace. Does anyone know why this should not be implemented (other than because you can do it without this)? Alternatively, does anyone have better ideas? That's called a spawn. For it to work correctly, you need to have a wait: while ((netfd = netopen ()) >= 0) { if ((pid = fork ()) == 0) { if (fork ()) exit (0); workhorse (); exit (0); } wait (0); /* clean up child, leave granchild */ close (netfd); } and some error checking and fork retrying is quite useful in practice. I prefer SIGCHLD, myself. It's too bad select wasn't made general enough to allow selecting on dead or stopped processes as well as file and socket conditions. -- John Quarterman, CS Dept., University of Texas, Austin, Texas {ihnp4,seismo,ctvax}!ut-sally!jsq, jsq@ut-sally.{ARPA,UUCP}
guy@rlgvax.UUCP (Guy Harris) (01/17/84)
As for "select" working for "wait", I presume the intent was that when "wait" was implemented as a "read" on a descriptor for the child process, one could do "select"s to see if a child was dead. Guy Harris {seismo,ihnp4,allegra}!rlgvax!guy
gwyn%brl-vld@sri-unix.UUCP (01/17/84)
From: Doug Gwyn (VLD/VMB) <gwyn@brl-vld> Being able to do something acceptably without adding a new system call seems to me to be sufficient reason for not adding the system call.
gwyn%brl-vld@sri-unix.UUCP (01/17/84)
From: Doug Gwyn (VLD/VMB) <gwyn@brl-vld> One thing you didn't mention is that wait(2) will block until all children have terminated under UNIX System V if SIGCLD is set to SIG_IGN. On 4.1cBSD at least, setting the handler for SIGCHLD to SIG_IGN was NOT the same as setting it to SIG_DFL in that this state was detectable by user code as a non-default mode. I found this out the hard way when my wait(2) emulation for UNIX System V on 4.1cBSD went into a loop when emulated code was run by csh or telnetd users. Turns out csh and telnetd were sloppy about resetting SIGCHLD and had set it to SIG_IGN by mistake. The 4.1cBSD manual had more information about this than the 4.2BSD manual seems to have. I urge people to set SIGCHLD to SIG_DFL if they want it totally ignored, since SIG_IGN has different semantics for UNIX System V programs.