Commit a84b9932 by Alexander Vladimirov Committed by Stéphane Graber

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: 's avatarAlexander Vladimirov <alexander.idkfa.vladimirov@gmail.com> Acked-by: 's avatarSerge E. Hallyn <serge.hallyn@ubuntu.com>
parent da139233
......@@ -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
......
......@@ -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
};
......
......@@ -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)
{
......
......@@ -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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment