From: Christian Brauner Date: Sun, 12 Nov 2017 14:25:19 +0000 (+0100) Subject: console: prepare for generic signal handler X-Git-Tag: lxc-2.0.10~574 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f1a39390a46ec5318b8198c8520061f0c4857abb;p=thirdparty%2Flxc.git console: prepare for generic signal handler Non-functional changes to enable handling more signals. Signed-off-by: Christian Brauner --- diff --git a/src/lxc/console.c b/src/lxc/console.c index 72c01b192..76bf08be5 100644 --- a/src/lxc/console.c +++ b/src/lxc/console.c @@ -57,25 +57,39 @@ static struct lxc_list lxc_ttys; typedef void (*sighandler_t)(int); -__attribute__((constructor)) -void lxc_console_init(void) +__attribute__((constructor)) void lxc_console_init(void) { lxc_list_init(&lxc_ttys); } void lxc_console_winsz(int srcfd, int dstfd) { + int ret; struct winsize wsz; - if (isatty(srcfd) && ioctl(srcfd, TIOCGWINSZ, &wsz) == 0) { - DEBUG("set winsz dstfd:%d cols:%d rows:%d", dstfd, - wsz.ws_col, wsz.ws_row); - ioctl(dstfd, TIOCSWINSZ, &wsz); + + if (!isatty(srcfd)) + return; + + ret = ioctl(srcfd, TIOCGWINSZ, &wsz); + if (ret < 0) { + WARN("Failed to get window size"); + return; } + + ret = ioctl(dstfd, TIOCSWINSZ, &wsz); + if (ret < 0) + WARN("Failed to set window size"); + else + DEBUG("Set window size to %d columns and %d rows", wsz.ws_col, + wsz.ws_row); + + return; } static void lxc_console_winch(struct lxc_tty_state *ts) { lxc_console_winsz(ts->stdinfd, ts->masterfd); + if (ts->winch_proxy) lxc_cmd_console_winch(ts->winch_proxy, ts->winch_proxy_lxcpath); } @@ -91,15 +105,15 @@ void lxc_console_sigwinch(int sig) } } -int lxc_console_cb_sigwinch_fd(int fd, uint32_t events, void *cbdata, - struct lxc_epoll_descr *descr) +int lxc_console_cb_signal_fd(int fd, uint32_t events, void *cbdata, + struct lxc_epoll_descr *descr) { struct signalfd_siginfo siginfo; struct lxc_tty_state *ts = cbdata; ssize_t ret = read(fd, &siginfo, sizeof(siginfo)); if (ret < 0 || (size_t)ret < sizeof(siginfo)) { - ERROR("failed to read signal info"); + ERROR("Failed to read signal info"); return -1; } @@ -107,8 +121,9 @@ int lxc_console_cb_sigwinch_fd(int fd, uint32_t events, void *cbdata, return 0; } -struct lxc_tty_state *lxc_console_sigwinch_init(int srcfd, int dstfd) +struct lxc_tty_state *lxc_console_signal_init(int srcfd, int dstfd) { + bool istty; sigset_t mask; struct lxc_tty_state *ts; @@ -121,7 +136,8 @@ struct lxc_tty_state *lxc_console_sigwinch_init(int srcfd, int dstfd) ts->masterfd = dstfd; ts->sigfd = -1; - if (!isatty(srcfd)) { + istty = isatty(srcfd) == 1; + if (!istty) { INFO("fd %d does not refer to a tty device", srcfd); return ts; } @@ -133,7 +149,7 @@ 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"); + SYSERROR("Failed to block SIGWINCH signal"); ts->sigfd = -1; lxc_list_del(&ts->node); return ts; @@ -141,18 +157,18 @@ struct lxc_tty_state *lxc_console_sigwinch_init(int srcfd, int dstfd) ts->sigfd = signalfd(-1, &mask, 0); if (ts->sigfd < 0) { - SYSERROR("failed to create signal fd"); + SYSERROR("Failed to create signal fd"); sigprocmask(SIG_SETMASK, &ts->oldmask, NULL); ts->sigfd = -1; lxc_list_del(&ts->node); return ts; } - DEBUG("process %d created signal fd %d to handle SIGWINCH events", getpid(), ts->sigfd); + DEBUG("Process %d created signal fd %d", getpid(), ts->sigfd); return ts; } -void lxc_console_sigwinch_fini(struct lxc_tty_state *ts) +void lxc_console_signal_fini(struct lxc_tty_state *ts) { if (ts->sigfd >= 0) { close(ts->sigfd); @@ -176,7 +192,7 @@ static int lxc_console_cb_con(int fd, uint32_t events, void *data, lxc_mainloop_del_handler(descr, fd); if (fd == console->peer) { if (console->tty_state) { - lxc_console_sigwinch_fini(console->tty_state); + lxc_console_signal_fini(console->tty_state); console->tty_state = NULL; } console->peer = -1; @@ -209,16 +225,15 @@ static void lxc_console_mainloop_add_peer(struct lxc_console *console) if (console->peer >= 0) { if (lxc_mainloop_add_handler(console->descr, console->peer, lxc_console_cb_con, console)) - WARN("console peer not added to mainloop"); + WARN("Failed to add console peer handler to mainloop"); } 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, + lxc_console_cb_signal_fd, console->tty_state)) { - WARN("failed to add to mainloop SIGWINCH handler for '%d'", - console->tty_state->sigfd); + WARN("Failed to add signal handler to mainloop"); } } } @@ -305,7 +320,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) { - lxc_console_sigwinch_fini(console->tty_state); + lxc_console_signal_fini(console->tty_state); console->tty_state = NULL; } close(console->peerpty.master); @@ -351,7 +366,7 @@ static int lxc_console_peer_proxy_alloc(struct lxc_console *console, int sockfd) if (lxc_setup_tios(console->peerpty.slave, &oldtermio) < 0) goto err1; - ts = lxc_console_sigwinch_init(console->peerpty.master, console->master); + ts = lxc_console_signal_init(console->peerpty.master, console->master); if (!ts) goto err1; @@ -463,10 +478,10 @@ static int lxc_console_peer_default(struct lxc_console *console) goto on_error1; } - ts = lxc_console_sigwinch_init(console->peer, console->master); + ts = lxc_console_signal_init(console->peer, console->master); console->tty_state = ts; if (!ts) { - WARN("unable to install SIGWINCH handler"); + WARN("Failed to install signal handler"); goto on_error1; } @@ -683,7 +698,7 @@ int lxc_console(struct lxc_container *c, int ttynum, if (ret < 0) TRACE("Process is already group leader"); - ts = lxc_console_sigwinch_init(stdinfd, masterfd); + ts = lxc_console_signal_init(stdinfd, masterfd); if (!ts) { ret = -1; goto close_fds; @@ -709,9 +724,9 @@ int lxc_console(struct lxc_container *c, int ttynum, if (ts->sigfd != -1) { ret = lxc_mainloop_add_handler(&descr, ts->sigfd, - lxc_console_cb_sigwinch_fd, ts); + lxc_console_cb_signal_fd, ts); if (ret < 0) { - ERROR("Failed to add SIGWINCH handler"); + ERROR("Failed to add signal handler to mainloop"); goto close_mainloop; } } @@ -765,7 +780,7 @@ close_mainloop: lxc_mainloop_close(&descr); sigwinch_fini: - lxc_console_sigwinch_fini(ts); + lxc_console_signal_fini(ts); close_fds: close(masterfd); diff --git a/src/lxc/console.h b/src/lxc/console.h index fefdb19e2..b5a9e0d02 100644 --- a/src/lxc/console.h +++ b/src/lxc/console.h @@ -24,6 +24,9 @@ #ifndef __LXC_CONSOLE_H #define __LXC_CONSOLE_H +#include +#include + #include "conf.h" #include "list.h" @@ -38,18 +41,21 @@ struct lxc_tty_state /* Escape sequence to use for exiting the pty. A single char can be * specified. The pty can then exited by doing: Ctrl + specified_char + q. * This field is checked by lxc_console_cb_tty_stdin(). Set to -1 to - * disable exiting the pty via a escape sequence. */ + * disable exiting the pty via a escape sequence. + */ int escape; /* Used internally by lxc_console_cb_tty_stdin() to check whether an - * escape sequence has been received. */ + * escape sequence has been received. + */ int saw_escape; /* Name of the container to forward the SIGWINCH event to. */ 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. If set to -1 no - * SIGWINCH handler could be installed. This also means that - * the sigset_t oldmask member is meaningless. */ + /* File descriptor that accepts signals. If set to -1 no signal handler + * could be installed. This also means that the sigset_t oldmask member + * is meaningless. + */ int sigfd; sigset_t oldmask; }; @@ -172,47 +178,47 @@ extern int lxc_setup_tios(int fd, struct termios *oldtios); extern void lxc_console_winsz(int srcfd, int dstfd); /* - * lxc_console_sigwinch_init: install SIGWINCH handler + * lxc_console_signal_init: install signal handler * * @srcfd : src for winsz in SIGWINCH handler * @dstfd : dst for winsz in SIGWINCH handler * * Returns lxc_tty_state structure on success or NULL on failure. The sigfd * member of the returned lxc_tty_state can be select()/poll()ed/epoll()ed - * on (ie added to a mainloop) for SIGWINCH. + * on (ie added to a mainloop) for signals. * * Must be called with process_lock held to protect the lxc_ttys list, or * from a non-threaded context. * - * Note that SIGWINCH isn't installed as a classic asychronous handler, - * rather signalfd(2) is used so that we can handle the signal when we're - * ready for it. This avoids deadlocks since a signal handler - * (ie lxc_console_sigwinch()) would need to take the thread mutex to - * prevent lxc_ttys list corruption, but using the fd we can provide the - * tty_state needed to the callback (lxc_console_cb_sigwinch_fd()). + * Note that the signal handler isn't installed as a classic asychronous + * handler, rather signalfd(2) is used so that we can handle the signal when + * we're ready for it. This avoids deadlocks since a signal handler (ie + * lxc_console_sigwinch()) would need to take the thread mutex to prevent + * lxc_ttys list corruption, but using the fd we can provide the tty_state + * needed to the callback (lxc_console_cb_signal_fd()). * * This function allocates memory. It is up to the caller to free it. */ -extern struct lxc_tty_state *lxc_console_sigwinch_init(int srcfd, int dstfd); +extern struct lxc_tty_state *lxc_console_signal_init(int srcfd, int dstfd); /* - * Handler for SIGWINCH events. To be registered via the corresponding functions + * Handler for signal events. To be registered via the corresponding functions * declared and defined in mainloop.{c,h} or lxc_console_mainloop_add(). */ -extern int lxc_console_cb_sigwinch_fd(int fd, uint32_t events, void *cbdata, - struct lxc_epoll_descr *descr); +extern int lxc_console_cb_signal_fd(int fd, uint32_t events, void *cbdata, + struct lxc_epoll_descr *descr); /* - * lxc_console_sigwinch_fini: uninstall SIGWINCH handler + * lxc_console_signal_fini: uninstall signal handler * - * @ts : the lxc_tty_state returned by lxc_console_sigwinch_init + * @ts : the lxc_tty_state returned by lxc_console_signal_init * * Restore the saved signal handler that was in effect at the time - * lxc_console_sigwinch_init() was called. + * lxc_console_signal_init() was called. * * Must be called with process_lock held to protect the lxc_ttys list, or * from a non-threaded context. */ -extern void lxc_console_sigwinch_fini(struct lxc_tty_state *ts); +extern void lxc_console_signal_fini(struct lxc_tty_state *ts); #endif diff --git a/src/lxc/tools/lxc_attach.c b/src/lxc/tools/lxc_attach.c index 2727d4261..beb122048 100644 --- a/src/lxc/tools/lxc_attach.c +++ b/src/lxc/tools/lxc_attach.c @@ -371,7 +371,7 @@ err3: lxc_mainloop_close(&descr); err2: if (ts && ts->sigfd != -1) - lxc_console_sigwinch_fini(ts); + lxc_console_signal_fini(ts); err1: lxc_console_delete(&conf->console);