Fix a long-standing bug inherited from FreeBSD. It is possible for a
authorMatthew Dillon <dillon@dragonflybsd.org>
Tue, 10 Oct 2006 15:40:47 +0000 (15:40 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Tue, 10 Oct 2006 15:40:47 +0000 (15:40 +0000)
commit167e6ecba2a139576866996945521464379d3cc3
treeac7a4418a70b111cbae94042dcadf27036803db0
parent78730e0ffaed08b3146d58ecdcb0d8adbc095be2
Fix a long-standing bug inherited from FreeBSD.  It is possible for a
signal sent to a process group to race a fork().  If the signal is received
by the process doing the fork() before it finishes hooking up the new child
to the process group the new child will not receive the signal.  The result
is that ^C does not always kill all the processes in the process group.

The problem occurs on UP systems if fork1() in the kernel blocks prior to
finishing the process setup.  Such blocking can occur in MALLOC.  The problem
can also occur if an interrupt occurs just as the process issues the fork()
system call, or on SMP systems where the signal is sent from a different cpu.

The solution is to use a lockmgr() lock to interlock the pgrp structure when
a signal is being sent to a process group and to have fork() check for
signal pre-conditions and return ERESTART if such conditions exist to force
processing of the pending signals.

NOTE!  BMAKE, MAKE, GNUMAKE ALSO HAVE UNRELATED SIGNALING BUGS.  These
programs improperly install a SIG_IGN for a few microseconds in order to
test the current signal function for SIGINT and various other signals.
If a ^C is sent while *MAKE is in this window, the *MAKE will ignore the
signal.

Reviewed-by: "Simon 'corecode' Schubert" <corecode@fs.ei.tum.de>
sys/kern/kern_fork.c
sys/kern/kern_proc.c
sys/kern/kern_sig.c
sys/sys/proc.h
sys/sys/signalvar.h
sys/sys/unistd.h