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

Reply via email to