ZyklonB: factor out on_plugin_death()

This commit is contained in:
Přemysl Eric Janouch 2015-06-15 00:53:42 +02:00
parent 634841ea18
commit e34ecd6bb9
1 changed files with 46 additions and 40 deletions

View File

@ -1744,6 +1744,49 @@ parse_config (struct bot_context *ctx, struct error **e)
return false;
}
static void
on_plugin_death (struct plugin *plugin, int status)
{
struct bot_context *ctx = plugin->ctx;
// TODO: callbacks on children death, so that we may tell the user
// "plugin `name' died like a dirty jewish pig"; use `status'
if (!plugin->is_zombie && WIFSIGNALED (status))
{
const char *notes = "";
#ifdef WCOREDUMP
if (WCOREDUMP (status))
notes = " (core dumped)";
#endif
print_warning ("Plugin `%s' died from signal %d%s",
plugin->name, WTERMSIG (status), notes);
}
// Let's go through the zombie state to simplify things a bit
// TODO: might not be a completely bad idea to restart the plugin
plugin_zombify (plugin);
plugin->pid = -1;
// In theory we could close `read_fd', set `read_event->closed' to true
// and expect epoll to no longer return events for the descriptor, as
// all the pipe ends should be closed by then (the child is dead, so its
// pipe FDs have been closed [assuming it hasn't forked without closing
// the descriptors, which would be evil], and we would have closed all
// of our FDs for this pipe as well). In practice that doesn't work.
poller_fd_reset (&plugin->read_event);
xclose (plugin->read_fd);
plugin->read_fd = -1;
LIST_UNLINK (ctx->plugins, plugin);
plugin_free (plugin);
free (plugin);
// Living child processes block us from quitting
try_finish_quit (ctx);
}
static void
on_signal_pipe_readable (const struct pollfd *fd, struct bot_context *ctx)
{
@ -1781,46 +1824,9 @@ on_signal_pipe_readable (const struct pollfd *fd, struct bot_context *ctx)
break;
struct plugin *plugin = plugin_find_by_pid (ctx, zombie);
// Something has died but we don't recognize it (re-exec?)
if (!soft_assert (plugin != NULL))
continue;
// TODO: callbacks on children death, so that we may tell the user
// "plugin `name' died like a dirty jewish pig"; use `status'
if (!plugin->is_zombie && WIFSIGNALED (status))
{
const char *notes = "";
#ifdef WCOREDUMP
if (WCOREDUMP (status))
notes = " (core dumped)";
#endif
print_warning ("Plugin `%s' died from signal %d%s",
plugin->name, WTERMSIG (status), notes);
}
// Let's go through the zombie state to simplify things a bit
// TODO: might not be a completely bad idea to restart the plugin
plugin_zombify (plugin);
plugin->pid = -1;
// In theory we could close `read_fd', set `read_event->closed' to true
// and expect epoll to no longer return events for the descriptor, as
// all the pipe ends should be closed by then (the child is dead, so its
// pipe FDs have been closed [assuming it hasn't forked without closing
// the descriptors, which would be evil], and we would have closed all
// of our FDs for this pipe as well). In practice that doesn't work.
poller_fd_reset (&plugin->read_event);
xclose (plugin->read_fd);
plugin->read_fd = -1;
LIST_UNLINK (ctx->plugins, plugin);
plugin_free (plugin);
free (plugin);
// Living child processes block us from quitting
try_finish_quit (ctx);
// XXX: re-exec if something has died that we don't recognize?
if (soft_assert (plugin != NULL))
on_plugin_death (plugin, status);
}
}