aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--zyklonb.c86
1 files changed, 46 insertions, 40 deletions
diff --git a/zyklonb.c b/zyklonb.c
index 01c7089..6b06caa 100644
--- a/zyklonb.c
+++ b/zyklonb.c
@@ -1745,6 +1745,49 @@ parse_config (struct bot_context *ctx, struct error **e)
}
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)
{
char dummy;
@@ -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);
}
}