chiark / gitweb /
SIGTERM and wait for subprocesses on server shutdown.
authorRichard Kettlewell <rjk@greenend.org.uk>
Sat, 24 Oct 2009 16:48:05 +0000 (17:48 +0100)
committerRichard Kettlewell <rjk@greenend.org.uk>
Sat, 24 Oct 2009 16:48:05 +0000 (17:48 +0100)
lib/event.c
lib/event.h
server/state.c

index ee25024..0c1e99a 100644 (file)
@@ -754,6 +754,38 @@ int ev_child_cancel(ev_source *ev,
   return 0;
 }
 
+/** @brief Terminate and wait for all child processes
+ * @param ev Event loop
+ *
+ * Does *not* call the completion callbacks.  Only used during teardown.
+ */
+void ev_child_killall(ev_source *ev) {
+  int n, rc, w;
+
+  for(n = 0; n < ev->nchildren; ++n) {
+    if(kill(ev->children[n].pid, SIGTERM) < 0) {
+      error(errno, "sending SIGTERM to pid %lu",
+           (unsigned long)ev->children[n].pid);
+      ev->children[n].pid = -1;
+    } else
+      info("sent SIGTERM to pid %lu", (unsigned long)ev->children[n].pid);
+  }
+  for(n = 0; n < ev->nchildren; ++n) {
+    if(ev->children[n].pid == -1)
+      continue;
+    do {
+      rc = waitpid(ev->children[n].pid, &w, 0);
+    } while(rc < 0 && errno == EINTR);
+    if(rc < 0) {
+      error(errno, "waiting for pid %lu", (unsigned long)ev->children[n].pid);
+      continue;
+    }
+    info("pid %lu exited with status %#x",
+        (unsigned long)ev->children[n].pid, w);
+  }
+  ev->nchildren = 0;
+}
+
 /* socket listeners ***********************************************************/
 
 /** @brief State for a socket listener */
index 2838c41..113666c 100644 (file)
@@ -139,6 +139,8 @@ int ev_child_cancel(ev_source *ev,
                    pid_t pid);
 /* cancel a child callback. */
 
+void ev_child_killall(ev_source *ev);
+
 /* socket listeners ***********************************************************/
 
 typedef int ev_listen_callback(ev_source *ev,
index bd74b14..47bb75c 100644 (file)
@@ -50,6 +50,22 @@ void quit(ev_source *ev) {
   quitting(ev);
   trackdb_close();
   trackdb_deinit();
+  /* Shutdown subprocesses.
+   *
+   * Subprocesses that use ev_child:
+   * - the speaker
+   * - the current rescan
+   * - any decoders
+   * - ...and players
+   * - the track picker
+   * - mail sender
+   * - the deadlock manager
+   *
+   * Subprocesses that don't:
+   * - any normalizers
+   * These are not shut down currently.
+   */
+  ev_child_killall(ev);
   info("exiting");
   exit(0);
 }