[net.unix-wizards] fork timing hole ???...

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

<oog>

	The Scenario
	------------

You type

	"ls<ret><del>"

Where <del> is the interrupt key of choice and the space between <ret> and <del>
is very fast (try two fingers poised for action).

What happens? 1 of 3 things

1) 

$ ls

$

2)

$ ls
$

3)

$ ls
my
local
files
$

BTW this has been repeated on several System 5/5.2 boxes as well as
4.1on a Vax  (4.2 is not available here). It would probably be hard
to reproduce on a Cray ... unless you have REALLY fast fingers.

In 1) ls (or its shell prior to execing) was forked and then received the
signal and died. In 2) the parent shell received the signal prior to calling
fork(). In 3) the signal arrives between when the parent shell enters fork()
and the new process is created (specifically before its process group is
filled in in its proc entry). 

The main reason for this is that newproc() doesn't copy pending signals from
the parents proc entry to the child.

Finally, my question ..... Is this a bug??

And the next, as yet unanswered question .... Should children inherit pending
signals?? .... Will it do any harm??



		Paul Campbell
		..!ucbvax!unisoft!paul

rml@hpfcla.UUCP (08/22/85)

>         In 3) the signal arrives between when the parent shell enters fork()
> and the new process is created (specifically before its process group is
> filled in in its proc entry). 
> 
> The main reason for this is that newproc() doesn't copy pending signals from
> the parents proc entry to the child.
> 
> Finally, my question ..... Is this a bug??

It does seem like a bug, although a rather minor one in practice.  In
the scenario you give, when the window is hit, most likely either

	a) the command which wasn't killed completes and the user
	   doesn't mind
or
	b) the user hits the interrupt key again to kill it.

Since there we're dealing with human reaction times here, there doesn't
seem to be any real harm done.  In a similar scenario with another
process sending a signal to the process group with kill(2), the bug
might be more severe.

> And the next, as yet unanswered question .... Should children inherit pending
> signals?? .... Will it do any harm??

No, I don't think children should inherit pending signals.  In this
particular case the signal was sent to the entire process group, and
thus it could be interpreted as being intended for the child as well.
However, ALL pending signals can include signals which have been
specifically sent to the parent process by kill(2).  If the child
inherited signals we would again have three possible situations:

	1) parent receives signal before fork
	2) parent receives signal after fork
	3) parent and child both receive signal

with the third being an anomaly caused by hitting a small window.  The
kernel currently has no way to distinguish signals sent to an individual
process from those sent to a process group (or to pid -1).  I suppose
such a mechanism could be added and the appropriate signals could be
passed across forks, but I'm not sure it would be worthwhile.

Also, inheriting signals across forks would have more impact on systems
which allow masking of signals (mainly 4.2 and those with signal
mechanisms based on 4.2).  On those systems the set of pending signals
is not limited to those arriving in the small window during fork.  It
could be argued that this would provide more correct semantics, but it's
not compatible with existing systems.

			Bob Lenk
			{hplabs, ihnp4}!hpfcla!rml

wood@rtp47.UUCP (Tom Wood) (08/23/85)

> Finally, my question ..... Is this a bug??
> And the next, as yet unanswered question .... Should children inherit pending
> signals?? .... Will it do any harm??

        Yes, all UNIX implementations I've seen do suffer from an
incorrect implementation of sending signals to a process group.  The
manual for kill is quite correct though: when killing a process group,
the signal will be sent to all members of the process group.  Simply
stated, *one* signal sent to a process group should be received by *all*
its members.

        The problem with the implementation is that the typical UNIX
mind-set takes hold.  Killing a process group is simply killing each
process which is a member of the group, and everyone knows that killing
a process is just a matter of setting a bit.  This can be solved by the
following implementation.

        First, all signals sent to a process are differentiated by the
manner in which they were sent.  Suppose then, that we have two bit
arrays: incomming_signals_for_pid and incomming_signals_for_pgrp.  At
the time a fork operation is performed, the latter should be inherited
by the child, while the former should not.  This means that signals sent
to a specific process are not inherited, while those sent to a process
group are.  Furthermore, only those signals that have not yet been
processed are subject to being inherited.

        In support of this change, I won't stand too long on the fact
that this is entirely consistent with what is (not) stated in the manual
for fork!  All UNIX implementations I've seen clear the pending signal
vector in the child process.  However, I believe this change is
consistent with the intent of kill (and killpg), and behaves reasonably
when one considers the ability to block signals (as in BSD 4.2).

        So I think a child should inherit incomming signals (those that
have not been processed) which were sent to the parent's process group
as a natural course of inheriting the parent's process group.  The child
should not inherit incomming signals which were sent specifically to the
parent.

        The incomming_signals_for_pgrp vector would also suffice for
sending signals to a group of process's based on other selection
criteria such as Ken Lalonde's "kill by real user-id".
-- 
			Tom Wood	
			Data General, Research Triangle Park, NC
			{the known world}!mcnc!rti-sel!rtp47!wood