]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
lxc-attach: attach even without sigwinch handler 951/head
authorChristian Brauner <christian.brauner@mailbox.org>
Thu, 7 Apr 2016 15:10:20 +0000 (17:10 +0200)
committerChristian Brauner <christian.brauner@mailbox.org>
Thu, 7 Apr 2016 19:01:18 +0000 (21:01 +0200)
lxc_console_create() calls lxc_console_peer_default() which in turn calls
lxc_console_sigwinch_init() which sets up the lxc_tty_state struct for the
current pty. Prior to this commit lxc_console_sigwinch_init() would consider
failures to install a SIGWINCH handler fatal and and return NULL. This commit
makes failures to install a SIGWINCH handler non-fatal. In such cases the
lxc_tty_state struct will still be set up but the sigfd member, which contains
the fd which receives SIGWINCH events, will be set to -1. (This also entails
that the sigset_t oldmaks field is meaningless.) Callers of
lxc_console_sigwinch_init() and lxc_console_sigwinch_fini() should thus make
sure that sigfd >= 0 or sigfd != -1 before trying to register a SIGWINCH handler
in e.g. an lxc_mainloop or resetting the sigmask (cf. lxc_attach.c).

These changes also imply that lxc_console_sigwinch_init() only fails with
ENOMEM. Thus, all cases where lxc_console_sigwinch_init() returns NULL are to be
considered fatal. This wasn't the case before this commit.

Signed-off-by: Christian Brauner <christian.brauner@mailbox.org>
src/lxc/console.c
src/lxc/console.h
src/lxc/lxc_attach.c

index 5df73e4b27c227fe1e9dff788b3faf0e6a54b059..2ce3cc4cced38b2a58c5f2653be51b243d09ae2a 100644 (file)
@@ -118,9 +118,9 @@ struct lxc_tty_state *lxc_console_sigwinch_init(int srcfd, int dstfd)
                return NULL;
 
        memset(ts, 0, sizeof(*ts));
-       ts->stdinfd  = srcfd;
+       ts->stdinfd = srcfd;
        ts->masterfd = dstfd;
-       ts->sigfd    = -1;
+       ts->sigfd = -1;
 
        /* add tty to list to be scanned at SIGWINCH time */
        lxc_list_add_elem(&ts->node, ts);
@@ -129,26 +129,20 @@ struct lxc_tty_state *lxc_console_sigwinch_init(int srcfd, int dstfd)
        sigemptyset(&mask);
        sigaddset(&mask, SIGWINCH);
        if (sigprocmask(SIG_BLOCK, &mask, &ts->oldmask)) {
-               SYSERROR("failed to block SIGWINCH");
-               goto err1;
+               SYSERROR("failed to block SIGWINCH.");
+               ts->sigfd = -1;
+               return ts;
        }
 
        ts->sigfd = signalfd(-1, &mask, 0);
        if (ts->sigfd < 0) {
-               SYSERROR("failed to get signalfd");
-               goto err2;
+               SYSERROR("failed to get signalfd.");
+               sigprocmask(SIG_SETMASK, &ts->oldmask, NULL);
+               ts->sigfd = -1;
+               return ts;
        }
 
        DEBUG("%d got SIGWINCH fd %d", getpid(), ts->sigfd);
-       goto out;
-
-err2:
-       sigprocmask(SIG_SETMASK, &ts->oldmask, NULL);
-err1:
-       lxc_list_del(&ts->node);
-       free(ts);
-       ts = NULL;
-out:
        return ts;
 }
 
@@ -207,7 +201,7 @@ static void lxc_console_mainloop_add_peer(struct lxc_console *console)
                        WARN("console peer not added to mainloop");
        }
 
-       if (console->tty_state) {
+       if (console->tty_state && console->tty_state->sigfd != -1) {
                if (lxc_mainloop_add_handler(console->descr,
                                             console->tty_state->sigfd,
                                             lxc_console_cb_sigwinch_fd,
@@ -291,7 +285,7 @@ int lxc_setup_tios(int fd, struct termios *oldtios)
 
 static void lxc_console_peer_proxy_free(struct lxc_console *console)
 {
-       if (console->tty_state) {
+       if (console->tty_state && console->tty_state->sigfd != -1) {
                lxc_console_sigwinch_fini(console->tty_state);
                console->tty_state = NULL;
        }
@@ -446,9 +440,11 @@ static void lxc_console_peer_default(struct lxc_console *console)
                goto err1;
 
        ts = lxc_console_sigwinch_init(console->peer, console->master);
-       if (!ts)
-               WARN("Unable to install SIGWINCH");
        console->tty_state = ts;
+       if (!ts) {
+               WARN("Unable to install SIGWINCH");
+               goto err1;
+       }
 
        lxc_console_winsz(console->peer, console->master);
 
@@ -471,6 +467,7 @@ err1:
        console->peer = -1;
 out:
        DEBUG("no console peer");
+       return;
 }
 
 void lxc_console_delete(struct lxc_console *console)
@@ -695,11 +692,13 @@ int lxc_console(struct lxc_container *c, int ttynum,
                goto err3;
        }
 
-       ret = lxc_mainloop_add_handler(&descr, ts->sigfd,
-                                      lxc_console_cb_sigwinch_fd, ts);
-       if (ret) {
-               ERROR("failed to add handler for SIGWINCH fd");
-               goto err4;
+       if (ts->sigfd != -1) {
+               ret = lxc_mainloop_add_handler(&descr, ts->sigfd,
+                               lxc_console_cb_sigwinch_fd, ts);
+               if (ret) {
+                       ERROR("failed to add handler for SIGWINCH fd");
+                       goto err4;
+               }
        }
 
        ret = lxc_mainloop_add_handler(&descr, ts->stdinfd,
@@ -727,7 +726,8 @@ int lxc_console(struct lxc_container *c, int ttynum,
 err4:
        lxc_mainloop_close(&descr);
 err3:
-       lxc_console_sigwinch_fini(ts);
+       if (ts->sigfd != -1)
+               lxc_console_sigwinch_fini(ts);
 err2:
        close(masterfd);
        close(ttyfd);
index 1f0a070b1f6f07a89d512d5e356dd7113e2eaea2..d3ccd8b0c45e6d0c823fb8ede7bfa3db4b417b98 100644 (file)
@@ -47,7 +47,9 @@ struct lxc_tty_state
        const char *winch_proxy;
        /* Path of the container to forward the SIGWINCH event to. */
        const char *winch_proxy_lxcpath;
-       /* File descriptor that accepts SIGWINCH signals. */
+       /* File descriptor that accepts SIGWINCH signals. If set to -1 no
+        * SIGWINCH handler could be installed. This also means that
+        * the sigset_t oldmask member is meaningless. */
        int sigfd;
        sigset_t oldmask;
 };
index ffcd3d189d35243fe17618cc635b542476f4d43f..cdc56d6c8c4cb912bdcb31916cef8a1690dc2d29 100644 (file)
@@ -264,7 +264,6 @@ static int get_pty_on_host(struct lxc_container *c, struct wrapargs *wrap, int *
         * always do the correct thing. strdup() must be used since console.path
         * is free()ed when we call lxc_container_put(). */
        free(conf->console.path);
-       conf->console.path = NULL;
        conf->console.path = strdup("/dev/tty");
        if (!conf->console.path)
                return -1;
@@ -326,12 +325,17 @@ static int get_pty_on_host(struct lxc_container *c, struct wrapargs *wrap, int *
                goto err2;
        }
 
-       /* Register sigwinch handler in mainloop. */
-       ret = lxc_mainloop_add_handler(&descr, ts->sigfd,
-                       lxc_console_cb_sigwinch_fd, ts);
-       if (ret) {
-               ERROR("failed to add handler for SIGWINCH fd");
-               goto err3;
+       /* Register sigwinch handler in mainloop. When ts->sigfd == -1 it means
+        * we weren't able to install a sigwinch handler in
+        * lxc_console_create(). We don't consider this fatal and just move on.
+        */
+       if (ts->sigfd != -1) {
+               ret = lxc_mainloop_add_handler(&descr, ts->sigfd,
+                               lxc_console_cb_sigwinch_fd, ts);
+               if (ret) {
+                       ERROR("failed to add handler for SIGWINCH fd");
+                       goto err3;
+               }
        }
 
        /* Register i/o callbacks in mainloop. */
@@ -359,7 +363,8 @@ static int get_pty_on_host(struct lxc_container *c, struct wrapargs *wrap, int *
 err3:
        lxc_mainloop_close(&descr);
 err2:
-       lxc_console_sigwinch_fini(ts);
+       if (ts->sigfd != -1)
+               lxc_console_sigwinch_fini(ts);
 err1:
        lxc_console_delete(&conf->console);