From d03dffe012ca1807b396270a4b145bfb0ae6d63a Mon Sep 17 00:00:00 2001
From: Michael Stapelberg <michael@stapelberg.de>
Date: Sun, 11 Sep 2011 21:49:35 +0100
Subject: [PATCH] Kill left-over i3-nagbar processes on 'exit'

---
 src/cfgparse.y | 18 ++++++++++++++++++
 src/main.c     | 12 ++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/src/cfgparse.y b/src/cfgparse.y
index 7efecc92..ca2d0710 100644
--- a/src/cfgparse.y
+++ b/src/cfgparse.y
@@ -240,6 +240,18 @@ static void nagbar_exited(EV_P_ ev_child *watcher, int revents) {
     configerror_pid = -1;
 }
 
+/*
+ * Cleanup handler. Will be called when i3 exits. Kills i3-nagbar with signal
+ * SIGKILL (9) to make sure there are no left-over i3-nagbar processes.
+ *
+ */
+static void nagbar_cleanup(EV_P_ ev_cleanup *watcher, int revent) {
+    if (configerror_pid != -1) {
+        LOG("Sending SIGKILL (9) to i3-nagbar with PID %d\n", configerror_pid);
+        kill(configerror_pid, SIGKILL);
+    }
+}
+
 /*
  * Starts an i3-nagbar process which alerts the user that his configuration
  * file contains one or more errors. Also offers two buttons: One to launch an
@@ -283,6 +295,12 @@ static void start_configerror_nagbar(const char *config_path) {
     ev_child *child = smalloc(sizeof(ev_child));
     ev_child_init(child, &nagbar_exited, configerror_pid, 0);
     ev_child_start(main_loop, child);
+
+    /* install a cleanup watcher (will be called when i3 exits and i3-nagbar is
+     * still running) */
+    ev_cleanup *cleanup = smalloc(sizeof(ev_cleanup));
+    ev_cleanup_init(cleanup, nagbar_cleanup);
+    ev_cleanup_start(main_loop, cleanup);
 }
 
 /*
diff --git a/src/main.c b/src/main.c
index aee95f75..ea02bb6e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -163,6 +163,14 @@ static void xkb_got_event(EV_P_ struct ev_io *w, int revents) {
     DLOG("Done\n");
 }
 
+/*
+ * Exit handler which destroys the main_loop. Will trigger cleanup handlers.
+ *
+ */
+static void i3_exit() {
+    ev_loop_destroy(main_loop);
+}
+
 int main(int argc, char *argv[]) {
     //parse_cmd("[ foo ] attach, attach ; focus");
     int screens;
@@ -529,5 +537,9 @@ int main(int argc, char *argv[]) {
         start_application(exec_always->command);
     }
 
+    /* Make sure to destroy the event loop to invoke the cleeanup callbacks
+     * when calling exit() */
+    atexit(i3_exit);
+
     ev_loop(main_loop, 0);
 }