I remember discussion about implementing proper way to shutdown guests using different signals, so here's a patch proposal. It allows to use specific signal numbers to shutdown guests gracefully, for example SIGRTMIN+4 starts poweroff.target in systemd.
Signed-off-by: Alexander Vladimirov <alexander.idkfa.vladimi...@gmail.com> --- doc/lxc.conf.sgml.in | 23 ++++++++++++++ src/lxc/conf.h | 1 + src/lxc/confile.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lxc/stop.c | 6 +++- 4 files changed, 119 insertions(+), 1 deletion(-) diff --git a/doc/lxc.conf.sgml.in b/doc/lxc.conf.sgml.in index ae91221..8ff1f20 100644 --- a/doc/lxc.conf.sgml.in +++ b/doc/lxc.conf.sgml.in @@ -130,6 +130,29 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA </refsect2> <refsect2> + <title>Stop signal</title> + <para> + Allows to specify signal name or number, sent by lxc-stop to + shutdown the container. Different init systems could use + different signals to perform clean shutdown sequence. Option + allows signal to be specified in kill(1) fashion, e.g. + SIGKILL, SIGRTMIN+14, SIGRTMAX-10 or plain number. + </para> + <variablelist> + <varlistentry> + <term> + <option>lxc.stopsignal</option> + </term> + <listitem> + <para> + specify the signal used to stop the container + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect2> + + <refsect2> <title>Network</title> <para> The network section defines how the network is virtualized in diff --git a/src/lxc/conf.h b/src/lxc/conf.h index f20fb2f..61456ae 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -277,6 +277,7 @@ struct lxc_conf { #endif int maincmd_fd; int autodev; // if 1, mount and fill a /dev at start + int stopsignal; // signal used to stop container char *rcfile; // Copy of the top level rcfile we read }; diff --git a/src/lxc/confile.c b/src/lxc/confile.c index d350f01..8dbe83d 100644 --- a/src/lxc/confile.c +++ b/src/lxc/confile.c @@ -27,6 +27,8 @@ #include <unistd.h> #include <errno.h> #include <fcntl.h> +#include <ctype.h> +#include <signal.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/param.h> @@ -87,6 +89,7 @@ static int config_seccomp(const char *, const char *, struct lxc_conf *); static int config_includefile(const char *, const char *, struct lxc_conf *); static int config_network_nic(const char *, const char *, struct lxc_conf *); static int config_autodev(const char *, const char *, struct lxc_conf *); +static int config_stopsignal(const char *, const char *, struct lxc_conf *); static struct lxc_config_t config[] = { @@ -134,6 +137,34 @@ static struct lxc_config_t config[] = { { "lxc.seccomp", config_seccomp }, { "lxc.include", config_includefile }, { "lxc.autodev", config_autodev }, + { "lxc.stopsignal", config_stopsignal }, +}; + +struct signame { + int num; + char *name; +}; + +struct signame signames[] = { + { SIGHUP, "HUP" }, + { SIGINT, "INT" }, + { SIGQUIT, "QUIT" }, + { SIGILL, "ILL" }, + { SIGABRT, "ABRT" }, + { SIGFPE, "FPE" }, + { SIGKILL, "KILL" }, + { SIGSEGV, "SEGV" }, + { SIGPIPE, "PIPE" }, + { SIGALRM, "ALRM" }, + { SIGTERM, "TERM" }, + { SIGUSR1, "USR1" }, + { SIGUSR2, "USR2" }, + { SIGCHLD, "CHLD" }, + { SIGCONT, "CONT" }, + { SIGSTOP, "STOP" }, + { SIGTSTP, "TSTP" }, + { SIGTTIN, "TTIN" }, + { SIGTTOU, "TTOU" }, }; static const size_t config_size = sizeof(config)/sizeof(struct lxc_config_t); @@ -959,6 +990,65 @@ static int config_autodev(const char *key, const char *value, return 0; } +static int sig_num(const char *sig) +{ + int n; + char *endp = NULL; + + errno = 0; + n = strtol(sig, &endp, 10); + if (sig == endp || n < 0 || errno != 0) + return -1; + return n; +} + +static int rt_sig_num(const char *signame) +{ + int sig_n = 0; + int rtmax = 0; + + if (strncasecmp(signame, "max-", 4) == 0) { + rtmax = 1; + } + signame += 4; + if (!isdigit(*signame)) + return -1; + sig_n = sig_num(signame); + sig_n = rtmax ? SIGRTMAX - sig_n : SIGRTMIN + sig_n; + if (sig_n > SIGRTMAX || sig_n < SIGRTMIN) + return -1; + return sig_n; +} + +static int sig_parse(const char *signame) { + int n; + + if (isdigit(*signame)) { + return sig_num(signame); + } else if (strncasecmp(signame, "sig", 3) == 0) { + signame += 3; + if (strncasecmp(signame, "rt", 2) == 0) + return rt_sig_num(signame + 2); + for (n = 0; n < sizeof(signames) / sizeof((signames)[0]); n++) { + if (strcasecmp (signames[n].name, signame) == 0) + return signames[n].num; + } + } + return -1; +} + +static int config_stopsignal(const char *key, const char *value, + struct lxc_conf *lxc_conf) +{ + int sig_n = sig_parse(value); + + if (sig_n < 0) + return -1; + lxc_conf->stopsignal = sig_n; + + return 0; +} + static int config_cgroup(const char *key, const char *value, struct lxc_conf *lxc_conf) { diff --git a/src/lxc/stop.c b/src/lxc/stop.c index 851a4bf..7fea6b6 100644 --- a/src/lxc/stop.c +++ b/src/lxc/stop.c @@ -34,6 +34,7 @@ #include <lxc/log.h> #include <lxc/start.h> +#include <lxc/conf.h> #include "lxc.h" #include "commands.h" @@ -82,9 +83,12 @@ extern int lxc_stop_callback(int fd, struct lxc_request *request, { struct lxc_answer answer; int ret; + int stopsignal = SIGKILL; + if (handler->conf->stopsignal) + stopsignal = handler->conf->stopsignal; memset(&answer, 0, sizeof(answer)); - answer.ret = kill(handler->pid, SIGKILL); + answer.ret = kill(handler->pid, stopsignal); if (!answer.ret) { ret = lxc_unfreeze_bypath(handler->cgroup); if (!ret) -- 1.8.1.5 ------------------------------------------------------------------------------ Symantec Endpoint Protection 12 positioned as A LEADER in The Forrester Wave(TM): Endpoint Security, Q1 2013 and "remains a good choice" in the endpoint security space. For insight on selecting the right partner to tackle endpoint security challenges, access the full report. http://p.sf.net/sfu/symantec-dev2dev _______________________________________________ Lxc-devel mailing list Lxc-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/lxc-devel