Bug 228728

Summary: sh does not reap killed background processes until terminal activity, creating zombies
Product: Base System Reporter: Mahmoud Al-Qudsi <mqudsi>
Component: binAssignee: freebsd-bugs (Nobody) <bugs>
Status: New ---    
Severity: Affects Many People CC: emaste, jilles, mqudsi
Priority: ---    
Version: CURRENT   
Hardware: Any   
OS: Any   

Description Mahmoud Al-Qudsi 2018-06-03 20:13:24 UTC
The default `sh` shell does not reap backgrounded processes if sitting idle, and killed backgrounded processes are not reaped until a new command is executed or enter is pressed at the tty.

For example, 

$ cat
[1] + Suspended                     cat

Now in another terminal or in an SSH session:

$ killall -9 cat

The PID associated with cat is turned into a zombie as the shell does not reap the killed instance. The only way to trigger reaping would be to attach to the tty session where the process was initially backgrounded and hit <ENTER>:

$ cat
# resuming from first segment above 
[1] Killed                          cat

Solution: `waitpid(2)` should be used to asynchronously detect the exit of backgrounded child processes.
Comment 1 Jilles Tjoelker freebsd_committer 2018-06-03 21:57:06 UTC
If this is to be fixed, waitpid() alone does not suffice, since it does not let you wait for either terminal input or a process termination. It is necessary to have a SIGCHLD signal handler (either directly or via pselect(2)).

Due to limitations in libedit's API, the signal handler could not do much more than reap the zombie and register this in the struct job. This does not help much except system administrators that insist on zombies being reaped quickly. Things like a proper 'set -b' (notify about job state at any time) would require some way to execute a handler function in a defined environment and to redraw the pending input.