]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
lxc_monitord: make lxc-monitord async signal safe 1327/head
authorChristian Brauner <christian.brauner@ubuntu.com>
Sun, 27 Nov 2016 00:43:37 +0000 (01:43 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Sun, 27 Nov 2016 03:28:01 +0000 (04:28 +0100)
Before lxc_monitord called lxc_monitord_cleanup() from a signal handler.  This
function calls a bunch of async signal unsafe functions and basically begs for
deadlocks. This commit switches lxc-monitord to using sigsetjmp() and
siglongjmp() in the signal handler to jump to a cleanup label that call
lxc_monitord_cleanup(). In this way, we avoid using async signal unsafe
functions.

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/lxc_monitord.c

index 2500571c26aac59c98c6ff0b23e1a926b987dc81..2fbb3574fdb5a9e641948cffef713a64bfea921d 100644 (file)
@@ -31,6 +31,7 @@
 #include <unistd.h>
 #include <net/if.h>
 #include <netinet/in.h>
+#include <setjmp.h>
 #include <sys/epoll.h>
 #include <sys/param.h>
 #include <sys/socket.h>
@@ -48,6 +49,8 @@
 
 lxc_log_define(lxc_monitord, lxc);
 
+sigjmp_buf mark;
+
 static void lxc_monitord_cleanup(void);
 
 /*
@@ -336,9 +339,7 @@ static void lxc_monitord_cleanup(void)
 
 static void lxc_monitord_sig_handler(int sig)
 {
-       INFO("Caught signal %d.", sig);
-       lxc_monitord_cleanup();
-       exit(EXIT_SUCCESS);
+       siglongjmp(mark, 1);
 }
 
 int main(int argc, char *argv[])
@@ -384,6 +385,9 @@ int main(int argc, char *argv[])
        signal(SIGBUS,  lxc_monitord_sig_handler);
        signal(SIGTERM, lxc_monitord_sig_handler);
 
+       if (sigsetjmp(mark, 1) != 0)
+               goto on_signal;
+
        ret = EXIT_FAILURE;
        memset(&mon, 0, sizeof(mon));
        mon.lxcpath = lxcpath;
@@ -427,4 +431,8 @@ int main(int argc, char *argv[])
 
 on_error:
        exit(ret);
+
+on_signal:
+       lxc_monitord_cleanup();
+       exit(EXIT_SUCCESS);
 }