The fork1 routine can wait for the child to exit (if vforked) and/or
return the pointer to the child.
Neither case guarantees the safety of said operation. The key is that
the parent can be ignoring SIGCHLD, which results in autoreaping the
child and the child itself is made runnable. Thus in particular it can
exit and get its struct proc freed. No prevention measures are taken
I did not test it on the NetBSD kernel, but it's a standard problem and
the code definitely looks buggy.
1. returning the pointer
The last parameter to fork1 is struct proc **rnewprocp. I found only 2
- linux_sys_clone - the parameter is populated from a local variable
which is not used afterwards, i.e. the func can as well start passing
- creation of initproc - since this becomes the only remaining use of
the parameter I think it makes sense to get rid of it altogether. the
simplest hack which comes to mind will simply proc_find_raw the
process after fork return
By the end there is:
while (p2->p_lflag & PL_PPWAIT)
Retesting after wake up triggers the bug.
The cleanest solution I'm aware of introduces a dedicated condvar to use
by vfork. The parent uses a local variable for this purpose. Since the
condvar is only used by vfork to signal exec/exit, there is no need
to access the child after waking up. The downside is extention of struct
proc with a pointer. Interestingly this is what they do in Linux.
FreeBSD does the obvious of grabbing a reference preventing the
destruction of struct proc from going through.
Solaris suprisingly has a total hack: they look up the pid and see if
found process (if any) has to be waited on. Apart from general ugliness
it's also a minor scalability problem due to extra lock/unlock of the
global process list lock.