Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add lxc.stopsignal config option

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.vladimirov@gmail.com>
Acked-by: Serge E. Hallyn <serge.hallyn@ubuntu.com>
  • Loading branch information...
commit a84b99323ab760d67cf76ef2418313bfd4f8b3ca 1 parent da13923
@idkfa idkfa authored stgraber committed
View
23 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
View
1  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
};
View
90 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)
{
View
6 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)
Please sign in to comment.
Something went wrong with that request. Please try again.