Do not let unexpected signals trigger emergency shells (hummingbird.c): the waitpid call isn't guarded against EINTR errors. I believe this can fix #24 as I had similar symptoms when trying to use s6-rc (which double forks lots of processes during startup, sending a barrage of SIGCHLDs to PID 1). In between the "Service started" messages, the "Init failed, starting emergency shell..." message appeared, and a few seconds later the shutdown procedure began by itself (without me typing Ctrl+D or exit). This is consistent with the waitpid in execute() returning earlier than expected.
Reap as many children as possible per SIGCHLD (signal.c): After applying the above fix and booting successfully, had zombie processes laying around. Apparently the correct behavior is to reap as many zombies as possible per SIGCHLD as one signal might come with a batch of multiple reparented processes. TODO: ensure execute() will always reap the runlevel script (maybe a global variable?).
Tested on Gentoo with a tty script that spawns a s6-rc supervision tree.
errno is set implicitly by the waitpid() call, so no need to set it each iteration of the loop. Other than that, looks good, and my only complaint was in regards to code quality.
Do not let unexpected signals trigger emergency shells (hummingbird.c): the
waitpid
call isn't guarded against EINTR errors. I believe this can fix #24 as I had similar symptoms when trying to use s6-rc (which double forks lots of processes during startup, sending a barrage of SIGCHLDs to PID 1). In between the "Service started" messages, the "Init failed, starting emergency shell..." message appeared, and a few seconds later the shutdown procedure began by itself (without me typing Ctrl+D orexit
). This is consistent with thewaitpid
inexecute()
returning earlier than expected.Reap as many children as possible per SIGCHLD (signal.c): After applying the above fix and booting successfully, had zombie processes laying around. Apparently the correct behavior is to reap as many zombies as possible per SIGCHLD as one signal might come with a batch of multiple reparented processes. TODO: ensure
execute()
will always reap the runlevel script (maybe a global variable?).Tested on Gentoo with a tty script that spawns a s6-rc supervision tree.