diff --git a/zyklonb.c b/zyklonb.c index 6b06caa..3c147a5 100644 --- a/zyklonb.c +++ b/zyklonb.c @@ -1787,6 +1787,32 @@ on_plugin_death (struct plugin *plugin, int status) try_finish_quit (ctx); } +static bool +try_reap_plugin (struct bot_context *ctx) +{ + int status; + pid_t zombie = waitpid (-1, &status, WNOHANG); + + if (zombie == -1) + { + // No children to wait on + if (errno == ECHILD) + return false; + + hard_assert (errno == EINTR); + return true; + } + + if (zombie == 0) + return false; + + struct plugin *plugin = plugin_find_by_pid (ctx, zombie); + // XXX: re-exec if something has died that we don't recognize? + if (soft_assert (plugin != NULL)) + on_plugin_death (plugin, status); + return true; +} + static void on_signal_pipe_readable (const struct pollfd *fd, struct bot_context *ctx) { @@ -1803,31 +1829,10 @@ on_signal_pipe_readable (const struct pollfd *fd, struct bot_context *ctx) initiate_quit (ctx); } - // Reap all dead children (since the pipe may overflow, we ask waitpid() - // to return all the zombies it knows about). - while (true) - { - int status; - pid_t zombie = waitpid (-1, &status, WNOHANG); - - if (zombie == -1) - { - // No children to wait on - if (errno == ECHILD) - break; - - hard_assert (errno == EINTR); - continue; - } - - if (zombie == 0) - break; - - struct plugin *plugin = plugin_find_by_pid (ctx, zombie); - // XXX: re-exec if something has died that we don't recognize? - if (soft_assert (plugin != NULL)) - on_plugin_death (plugin, status); - } + // Reap all dead children (since the signal pipe may overflow etc. we run + // waitpid() in a loop to return all the zombies it knows about). + while (try_reap_plugin (ctx)) + ; } int