xpc: terminate daemon when last XPC connection to App gone
authorMartin Willi <martin@revosec.ch>
Thu, 2 May 2013 12:40:23 +0000 (14:40 +0200)
committerMartin Willi <martin@revosec.ch>
Thu, 18 Jul 2013 10:17:55 +0000 (12:17 +0200)
src/frontends/osx/charon-xpc/xpc_dispatch.c

index 1f636bc..1ef77bf 100644 (file)
@@ -17,6 +17,8 @@
 #include "xpc_channels.h"
 
 #include <xpc/xpc.h>
+#include <signal.h>
+#include <unistd.h>
 
 #include <daemon.h>
 #include <processing/jobs/callback_job.h>
@@ -47,6 +49,16 @@ struct private_xpc_dispatch_t {
         * GCD queue for XPC events
         */
        dispatch_queue_t queue;
+
+       /**
+        * Number of active App connections
+        */
+       refcount_t refcount;
+
+       /**
+        * PID of main thread
+        */
+       pid_t pid;
 };
 
 /**
@@ -258,6 +270,18 @@ static void handle(private_xpc_dispatch_t *this, xpc_object_t request)
 }
 
 /**
+ * Finalizer for client connections
+ */
+static void cleanup_connection(private_xpc_dispatch_t *this)
+{
+       if (ref_put(&this->refcount))
+       {
+               DBG1(DBG_CFG, "no XPC connections, raising SIGTERM");
+               kill(this->pid, SIGTERM);
+       }
+}
+
+/**
  * Set up GCD handler for XPC events
  */
 static void set_handler(private_xpc_dispatch_t *this)
@@ -271,6 +295,9 @@ static void set_handler(private_xpc_dispatch_t *this)
                                handle(this, event);
                        }
                });
+               ref_get(&this->refcount);
+               xpc_connection_set_context(conn, this);
+               xpc_connection_set_finalizer_f(conn, (void*)cleanup_connection);
                xpc_connection_resume(conn);
        });
        xpc_connection_resume(this->service);
@@ -303,6 +330,7 @@ xpc_dispatch_t *xpc_dispatch_create()
                .channels = xpc_channels_create(),
                .queue = dispatch_queue_create("org.strongswan.charon-xpc.q",
                                                                        DISPATCH_QUEUE_CONCURRENT),
+               .pid = getpid(),
        );
        charon->bus->add_listener(charon->bus, &this->channels->listener);