The following reply was made to PR kern/38670; it has been noted by GNATS.
From: Andrew Doran <ad@xxxxxxxxxx>
Cc: kern-bug-people@xxxxxxxxxx, gnats-admin@xxxxxxxxxx,
Subject: Re: kern/38670: ^Z does not work anymore for this program.
Date: Sun, 22 Feb 2009 19:13:50 +0000
[Just to re-iterate, the described behaviour came in with 4.4BSD. I may have
fixed a bug that prevented it from working as intended in NetBSD, at least
as far as I can tell. I'm not saying that the behaviour is correct. It has
been a couple of years so my memory of it is sketchy.]
I don't have time to look into this too deeply right now but at a glance it
seems that stop signals are left in the child's pending set but simply
ignored. If that is the case, the child should stop at its next interrupable
sleep after clearing vfork().
In the test for PL_PPWAIT in exec(), we could test for any pending signals
with sigispending(), and if so, do a signotify() on curlwp. That would make
it catch the signal immediately after exec() instead of at "some point in
the future". However this does not affect the test case in the PR.
If the problem is that the child simply does not stop, even while calling
e.g. sleep(), then the signal must be getting ripped out of its pending set.
> Changing that call to cv_wait_sig() ought to restore the previous
> behavior; however, it's not clear that this is a particularly good
> idea, because if a signal arrives and results in ERESTARTSYS there'll
> be another child process created, and if it results in EINTR then the
> parent and the child will both be running on the same stack in the
> same address space, and demons will fly out of someone's nose.
I'm not sure what the supposed deadlock is either. Maybe someone with access
to the CSRG SCCS files could tell us who made the modifiction. We could
arrange for a special-cased wait in the parent where it will obey STOP and a
few other conditions and handle it in-kernel, if it would help. Ugly though.
It may mean checking that we can arrange for the parent to die even if it
has a child from vfork().