[lxc-devel] [PATCH v2] add lxc.haltsignal for soft shutdown

Dwight Engen dwight.engen at oracle.com
Mon Jan 6 17:30:02 UTC 2014


- use this in the busybox template since busybox's init expects
  to receive SIGUSR1 to halt

- fix lxc.stopsignal to be output by write_config so lxcapi_clone()
  and lxcapi_save_config() will output it

Signed-off-by: Dwight Engen <dwight.engen at oracle.com>
---
v2: add lxc.conf documentation

 doc/lxc-stop.sgml.in     | 13 ++++++-------
 doc/lxc.conf.sgml.in     | 33 ++++++++++++++++++++++++++++-----
 src/lxc/conf.h           |  3 ++-
 src/lxc/confile.c        | 28 ++++++++++++++++++++++++++++
 src/lxc/lxccontainer.c   |  5 ++++-
 templates/lxc-busybox.in |  1 +
 6 files changed, 69 insertions(+), 14 deletions(-)

diff --git a/doc/lxc-stop.sgml.in b/doc/lxc-stop.sgml.in
index bdb0ef5..dc002c5 100644
--- a/doc/lxc-stop.sgml.in
+++ b/doc/lxc-stop.sgml.in
@@ -65,13 +65,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     <para>
       <command>lxc-stop</command> reboots, cleanly shuts down, or kills
       all the processes inside the container.  By default, it will
-      request a clean shutdown of the container (by sending SIGPWR to
-      the container), wait 60 seconds for the container to exit, and
-      returns.  If the container fails to cleanly exit, then after 60
-      seconds the container will be sent the
-      <command>lxc.stopsignal</command> to force it to shut down. If
-      <command>lxc.stopsignal</command> is not specified, the signal sent is
-      SIGKILL.
+      request a clean shutdown of the container by sending
+      <command>lxc.haltsignal</command> (defaults to SIGPWR) to
+      the container's init process, waiting up to 60 seconds for the container
+      to exit, and then returning. If the container fails to cleanly exit in
+      60 seconds, it will be sent the <command>lxc.stopsignal</command>
+      (defaults to SIGKILL) to force it to shut down.
     </para>
 	<para>
 	The <optional>-W</optional>, <optional>-r</optional>,
diff --git a/doc/lxc.conf.sgml.in b/doc/lxc.conf.sgml.in
index e6d9689..09c8076 100644
--- a/doc/lxc.conf.sgml.in
+++ b/doc/lxc.conf.sgml.in
@@ -156,13 +156,36 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     </refsect2>
 
     <refsect2>
+      <title>Halt signal</title>
+      <para>
+    Allows one to specify signal name or number, sent by lxc-stop to the
+    container's init process to cleanly shutdown the container. Different
+    init systems could use different signals to perform clean shutdown
+    sequence. This option allows the signal to be specified in kill(1)
+    fashion, e.g. SIGPWR, SIGRTMIN+14, SIGRTMAX-10 or plain number. The
+    default signal is SIGPWR. 
+      </para>
+      <variablelist>
+    <varlistentry>
+      <term>
+        <option>lxc.haltsignal</option>
+      </term>
+      <listitem>
+        <para>
+          specify the signal used to halt the container
+        </para>
+      </listitem>
+    </varlistentry>
+      </variablelist>
+    </refsect2>
+
+    <refsect2>
       <title>Stop signal</title>
       <para>
-    Allows one 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.
+    Allows one to specify signal name or number, sent by lxc-stop to forcibly
+    shutdown the container. This option allows signal to be specified in
+    kill(1) fashion, e.g. SIGKILL, SIGRTMIN+14, SIGRTMAX-10 or plain number.
+    The default signal is SIGKILL. 
       </para>
       <variablelist>
     <varlistentry>
diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index e881635..8efd0f3 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -307,7 +307,8 @@ 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
+	int haltsignal; // signal used to halt container
+	int stopsignal; // signal used to hard stop container
 	int kmsg;  // if 1, create /dev/kmsg symlink
 	char *rcfile;	// Copy of the top level rcfile we read
 
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index 0982b3e..d21fbec 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -90,6 +90,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_haltsignal(const char *, const char *, struct lxc_conf *);
 static int config_stopsignal(const char *, const char *, struct lxc_conf *);
 static int config_start(const char *, const char *, struct lxc_conf *);
 static int config_group(const char *, const char *, struct lxc_conf *);
@@ -142,6 +143,7 @@ static struct lxc_config_t config[] = {
 	{ "lxc.seccomp",              config_seccomp              },
 	{ "lxc.include",              config_includefile          },
 	{ "lxc.autodev",              config_autodev              },
+	{ "lxc.haltsignal",           config_haltsignal           },
 	{ "lxc.stopsignal",           config_stopsignal           },
 	{ "lxc.start.auto",           config_start                },
 	{ "lxc.start.delay",          config_start                },
@@ -1108,6 +1110,16 @@ static int rt_sig_num(const char *signame)
 	return sig_n;
 }
 
+static const char *sig_name(int signum) {
+	int n;
+
+	for (n = 0; n < sizeof(signames) / sizeof((signames)[0]); n++) {
+		if (n == signames[n].num)
+			return signames[n].name;
+	}
+	return "";
+}
+
 static int sig_parse(const char *signame) {
 	int n;
 
@@ -1125,6 +1137,18 @@ static int sig_parse(const char *signame) {
 	return -1;
 }
 
+static int config_haltsignal(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->haltsignal = sig_n;
+
+	return 0;
+}
+
 static int config_stopsignal(const char *key, const char *value,
 			  struct lxc_conf *lxc_conf)
 {
@@ -2119,6 +2143,10 @@ void write_config(FILE *fout, struct lxc_conf *c)
 		fprintf(fout, "lxc.pts = %d\n", c->pts);
 	if (c->ttydir)
 		fprintf(fout, "lxc.devttydir = %s\n", c->ttydir);
+	if (c->haltsignal)
+		fprintf(fout, "lxc.haltsignal = SIG%s\n", sig_name(c->haltsignal));
+	if (c->stopsignal)
+		fprintf(fout, "lxc.stopsignal = SIG%s\n", sig_name(c->stopsignal));
 	#if HAVE_SYS_PERSONALITY_H
 	switch(c->personality) {
 	case PER_LINUX32: fprintf(fout, "lxc.arch = x86\n"); break;
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 132f1a3..353b733 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -1307,6 +1307,7 @@ static bool lxcapi_shutdown(struct lxc_container *c, int timeout)
 {
 	bool retv;
 	pid_t pid;
+	int haltsignal = SIGPWR;
 
 	if (!c)
 		return false;
@@ -1318,7 +1319,9 @@ static bool lxcapi_shutdown(struct lxc_container *c, int timeout)
 	pid = c->init_pid(c);
 	if (pid <= 0)
 		return true;
-	kill(pid, SIGPWR);
+	if (c->lxc_conf->haltsignal)
+		haltsignal = c->lxc_conf->haltsignal;
+	kill(pid, haltsignal);
 	retv = c->wait(c, "STOPPED", timeout);
 	if (!retv && timeout > 0) {
 		c->stop(c);
diff --git a/templates/lxc-busybox.in b/templates/lxc-busybox.in
index 8232334..974377d 100644
--- a/templates/lxc-busybox.in
+++ b/templates/lxc-busybox.in
@@ -272,6 +272,7 @@ copy_configuration()
 
 grep -q "^lxc.rootfs" $path/config 2>/dev/null || echo "lxc.rootfs = $rootfs" >> $path/config
 cat <<EOF >> $path/config
+lxc.haltsignal = SIGUSR1
 lxc.utsname = $name
 lxc.tty = 1
 lxc.pts = 1
-- 
1.8.3.1




More information about the lxc-devel mailing list