Path: utzoo!attcan!uunet!cs.utexas.edu!usc!apple!ames!dftsrv!mimsy!chris From: chris@mimsy.UUCP (Chris Torek) Newsgroups: comp.unix.wizards Subject: Re: Looking for tcsh binary which uses vfork Keywords: tcsh, vfork, SunOS 4.0 Message-ID: <19496@mimsy.UUCP> Date: 9 Sep 89 16:11:28 GMT References: <243@paralogics.UUCP> <10941@smoke.BRL.MIL> <246@paralogics.UUCP> Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742 Lines: 93 In article <246@paralogics.UUCP> shaw@paralogics.UUCP (Guy Shaw) writes: >Chris Torek didn't seem to be saying that vfork() caused incorrect >behavior, only that there is something better. Actually, it causes (indirectly) correct behaviour. The C shell runs a pipeline such as a | b | c by doing the sequence <> if ((pgroup = vfork()) == 0) { <> <> <> } <> if (vfork() == 0) { <> <> <> <> } <> if (vfork() == 0) { <> <> <> } <> Since vfork() suspends the execution of the parent process until the child process either exec()s or exit()s, the `set tty pgroup' happens before any of the three child processes actually start running. Fork(), however, does *not* suspend the parent process, and suddenly we have a race to see whether the tty pgroup gets set in time. >>The accepted solution is to set the terminal's process group k+1 times >>when there are k children in a pipeline (or k times with the current >>system): once in each child and once in the parent. Setting the pgroup >>to whatever it is already is harmless, and this ensures that the pgroup >>is set by the time it needs to be. >Do you mean do a right-to-left series of TIOCSPGRP ioctl calls, >as well as setpgrp calls? Since there is a race, the order is (and must be) irrelevant. The Bourne shell happens to fork and exec in such an order that, in `a | b | c', the shell is the parent of processes `a' and `c', but process c is the parent of process b. The C shell (since it wants to do job control) makes sure that all three are direct descendents of the shell itself, and happens to fork `a' first, `b' second, and `c' third. >I take it that, the way things are now, process "a" >is the only one that bothers with a TIOCSPGRP. Sorry if I misunderstand >this, I have no source. This is correct, but the source itself is unnecessary in this case. We can deduce this from the `jobs' command: % sleep 1 | sleep 10 | sleep 30 & [1] 300 301 302 % jobs -l [1] - 300 Done sleep 1 | 301 Running sleep 10 | 302 sleep 30 % % sleep 10; jobs [1] - Done sleep 1 | sleep 10 | Running sleep 30 % sleep 20; jobs [1] - Done sleep 1 | sleep 10 | sleep 30 % This tells us that csh is the direct parent of each element of the pipeline (since it gets status updates when each child exits). If we assume that csh uses vfork() (and is deterministic), we can deduce that csh vfork()s once, the child runs the first command, the parent unsticks and vfork()s again, the child runs the second command, etc. The child of the first vfork() must exec the first command, or the `sleep 1' above would not have the first process ID. Since the first child of vfork is guaranteed to run first, it must be `a' that sets the tty pgroup (given that the tty pgroup is set only once). -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris