[net.unix-wizards] fork timing hole?

howard@cyb-eng.UUCP (Howard Johnson) (08/16/85)

Explanation:  If you look closely at the sh/csh code, you'll find cases
where sh and/or csh catch SIGINT and emit a newline.  Specifically, it's
the parent shell which does this if it's interrupted while waiting for
the child to terminate.  By the way, receipt of the interrupt character
generates a SIGINT for every process in the controlling terminal's
process group.

> The Scenario:
> 	"ls<ret><del>"
> What happens? 1 of 3 things
> 
> 1) 
> 
> $ ls
> 
> $
> 
> 2)
> 
> $ ls
> $
> 
> 3)
> 
> $ ls
> my
> local
> files
> $

>	... [wild speculation]

> Finally, my question ..... Is this a bug??
> 		Paul Campbell
> 		..!ucbvax!unisoft!paul

In the shell, yes; in the kernel, no.  (Just a little tip from
one of your customers, Paul.)
-- 
..!{seismo,topaz,mordor,harvard,gatech,nbires,ihnp4}!ut-sally!cyb-eng!howard
(ordered best to worst); also ..!{ut-ngp,shell}!cyb-eng!howard  +1 512 458 6609

pc@unisoft.UUCP (Paul Campbell) (08/16/85)

> Explanation:  If you look closely at the sh/csh code, you'll find cases
> where sh and/or csh catch SIGINT and emit a newline.  Specifically, it's
> the parent shell which does this if it's interrupted while waiting for
> the child to terminate.  By the way, receipt of the interrupt character
> generates a SIGINT for every process in the controlling terminal's
> process group.
> 
> >	... [wild speculation]

You miss my point, cases 1 and 2 I don't care about, but the third case ....
where the parent gets the signal and the child continues without receiving
the signal is the interesting one. During a fork the parent does not pass its
pending signals to the child, if an interrupt character is received after
the shell starts the fork call (enters kernel mode) and before the system
writes the process group in the proc table entry then the new process does
not belong to the parent's process group until this moment. During this
time any signals to the parent will not be received by the child.


		Paul Campbell
		..!ucbvax!unisoft!paul

trt@rti-sel.UUCP (Tom Truscott) (08/19/85)

> ... During a fork the parent does not pass its
> pending signals to the child, ...

It sure looks like a bug to me.
System calls should be atomic actions whenever possible,
and we should avoid funny stuff happening 'within' a syscall.
I think there are two (at least) fixes to this bug:
    1) Copy the appropriate pending signals to the child
	(simulating delivery *after* the fork is completed).
    2) Back out of the fork, deliver the signal, then restart
	(simulating delivery *before* the fork begins).

One detail in copying pending signals to the child is that
only signals delivered to the entire process group should be copied.
For example, if some process signals the parent with 'kill(parent, SIGINT)'
the child should not get it.
	Tom Truscott

howard@cyb-eng.UUCP (Howard Johnson) (08/22/85)

> > >	... [wild speculation]
> 
> You miss my point, cases 1 and 2 I don't care about, but the third case ....
> where the parent gets the signal and the child continues without receiving
> the signal is the interesting one.

	Your original posting did not focus strongly enough on the desired
issue; I see now what you were trying to say.  After perusing source code
for psignal(), fork(), newproc(), etc. in the kernel, I believe that the
race condition exists.  I believe that signals should be inherited from
the parent process in newproc().  Thus,

	...
	rpp->p_sigign = rip->p_sigign;
+	rpp->p_sig = rip->p_sig;
	...

(in newproc()) should close up the race condition you described (if the
added statment is made uninterruptible) without ill effect.

	I still think that the behavior you described (ls <CR><DEL>)
could also be caused by the child process receiving the signal after
it has called exit()--provided that the "ls" wasn't run on some huge
directory such as /bin or /usr/src/cmd.
-- 
..!{seismo,topaz,mordor,harvard,gatech,nbires,ihnp4}!ut-sally!cyb-eng!howard
(ordered best to worst); also ..!{ut-ngp,shell}!cyb-eng!howard  +1 512 458 6609

paul@unisoft.UUCP (Paul Campbell) (08/23/85)

Oh dear, a further problem arises ..... What does it mean for a the child (or
for that matter the parent of a successfull fork) to get a failure from
a fork() call? If the parent gets a failure it assumes that the child doesn't
exist. Well folks its can of worms time ..... maybe this one is best left
as is ...

	Paul Campbell
	..!ucbvax!unisoft!paul