[Lxc-users] container shutdown

Daniel Lezcano daniel.lezcano at free.fr
Mon Mar 19 00:05:56 UTC 2012


On 03/19/2012 12:00 AM, Serge Hallyn wrote:
> Hi,
>
> Thanks to Jäkel's and Fajar's great ideas, we can now cleanly shut down
> a container by sending it SIGPWR.  I'm attaching two ways to do that.
> In-line is a patch which modifies lxc-stop to take optional -s and -t
> args - -s for shutdown (meaning send SIGPWR), and -t for a timeout,
> after sending SIGPWR, to hard-kill the container.

That may make more sense to implement a lxc-reboot | lxc-shutdow script 
on top of on lxc-kill.

IMHO, I don't think adding a timeout is a good idea because the shutdown 
process may take more than the timeout to stop the services and the 
container could be killed while the services are doing some cleanup or 
flush or whatever. If this option is present, people will tend to use it 
instead of investigating if a service is stuck, or working, or flushing.
I would recommend to let the shutdown script to handle the timeout by 
themselves.





>
> Attached is a lxc-shutdown script (as an alternative) so lxc-stop can
> continue to work as it has.
>
> Both are in the bzr tree at
> lp:~serge-hallyn/ubuntu/precise/lxc/lxc-shutdown, which builds and gives
> you both.
>
> What do we prefer?
>
> thanks,
> -serge
>
> Signed-off-by: Serge Hallyn<serge.hallyn at canonical.com>
> ---
>   doc/lxc-stop.sgml.in |   10 ++++++++++
>   src/lxc/arguments.h  |    4 ++++
>   src/lxc/commands.c   |    8 ++++----
>   src/lxc/lxc.h        |    5 ++++-
>   src/lxc/lxc_stop.c   |   22 +++++++++++++++++++---
>   src/lxc/stop.c       |   27 +++++++++++++++++++++++++--
>   6 files changed, 66 insertions(+), 10 deletions(-)
>
> Index: lxc/doc/lxc-stop.sgml.in
> ===================================================================
> --- lxc.orig/doc/lxc-stop.sgml.in	2012-03-18 16:33:06.254906000 -0500
> +++ lxc/doc/lxc-stop.sgml.in	2012-03-18 16:34:11.970538920 -0500
> @@ -49,6 +49,7 @@
>     <refsynopsisdiv>
>       <cmdsynopsis>
>         <command>lxc-stop<replaceable>-n name</replaceable>
> +<optional>-s</optional>  <optional>-t timeout</optional>
>         </command>
>       </cmdsynopsis>
>     </refsynopsisdiv>
> @@ -62,6 +63,15 @@
>         longer accessible and can no be exited normally.
>       </para>
>
> +<para>
> +      If<optional>-s</optional>  (<optional>--shutdown</optional>) is
> +      specified, then ask the container to shut down cleanly by sending
> +      a<emphasis>SIGPWR</emphasis>  signal.  If<optional>-t timeout</optional>
> +      is also given, then<emphasis>timeout</emphasis>  seconds after sending
> +      SIGPWR, if the container is still up, proceed to kill the container.
> +      Note that<optional>-t timeout</optional>  implies<optional>-s</optional>.
> +</para>
> +
>     </refsect1>
>
>     &commonoptions;
> Index: lxc/src/lxc/arguments.h
> ===================================================================
> --- lxc.orig/src/lxc/arguments.h	2012-03-18 16:33:06.254906000 -0500
> +++ lxc/src/lxc/arguments.h	2012-03-18 16:34:19.442575978 -0500
> @@ -46,6 +46,10 @@
>   	const char *rcfile;
>   	const char *console;
>
> +	/* for lxc-stop */
> +	int timeout;
> +	int shutdown;
> +
>   	/* for lxc-checkpoint/restart */
>   	const char *statefile;
>   	int statefd;
> Index: lxc/src/lxc/commands.c
> ===================================================================
> --- lxc.orig/src/lxc/commands.c	2012-03-18 16:33:06.254906000 -0500
> +++ lxc/src/lxc/commands.c	2012-03-18 16:34:26.862612782 -0500
> @@ -162,10 +162,10 @@
>   	typedef int (*callback)(int, struct lxc_request *, struct lxc_handler *);
>
>   	callback cb[LXC_COMMAND_MAX] = {
> -		[LXC_COMMAND_TTY]   = lxc_console_callback,
> -		[LXC_COMMAND_STOP]  = lxc_stop_callback,
> -		[LXC_COMMAND_STATE] = lxc_state_callback,
> -		[LXC_COMMAND_PID]   = lxc_pid_callback,
> +		[LXC_COMMAND_TTY]       = lxc_console_callback,
> +		[LXC_COMMAND_STOP]      = lxc_stop_callback,
> +		[LXC_COMMAND_STATE]     = lxc_state_callback,
> +		[LXC_COMMAND_PID]       = lxc_pid_callback,
>   	};
>
>   	if (request->type<  0 || request->type>= LXC_COMMAND_MAX)
> Index: lxc/src/lxc/lxc_stop.c
> ===================================================================
> --- lxc.orig/src/lxc/lxc_stop.c	2012-03-18 16:33:06.254906000 -0500
> +++ lxc/src/lxc/lxc_stop.c	2012-03-18 17:24:47.137589512 -0500
> @@ -30,7 +30,18 @@
>
>   #include "arguments.h"
>
> +static int my_parser(struct lxc_arguments* args, int c, char* arg)
> +{
> +	switch (c) {
> +	case 's': args->shutdown = 1; break;
> +	case 't': args->timeout = arg; args->shutdown = 1; break;
> +	}
> +	return 0;
> +}
> +
>   static const struct option my_longopts[] = {
> +	{"shutdown", no_argument, 0, 's'},
> +	{"timeout", required_argument, 0, 't'},
>   	LXC_COMMON_OPTIONS
>   };
>
> @@ -42,10 +53,15 @@
>   lxc-stop stops a container with the identifier NAME\n\
>   \n\
>   Options :\n\
> -  -n, --name=NAME   NAME for name of the container\n",
> +  -n, --name=NAME   NAME for name of the container\n\
> +  -s, --shutdown    Ask container to shut down cleanly\n\
> +  -t, --timeout=t   Imply -s and hard-kill container after t seconds\n\
> +                    (default is -1, no timeout)\n",
>   	.options  = my_longopts,
> -	.parser   = NULL,
> +	.parser   = my_parser,
>   	.checker  = NULL,
> +	.timeout  = -1,
> +	.shutdown = 0,
>   };
>
>   int main(int argc, char *argv[])
> @@ -57,5 +73,5 @@
>   			 my_args.progname, my_args.quiet))
>   		return -1;
>
> -	return lxc_stop(my_args.name);
> +	return lxc_stop(my_args.name, my_args.shutdown, my_args.timeout);
>   }
> Index: lxc/src/lxc/stop.c
> ===================================================================
> --- lxc.orig/src/lxc/stop.c	2012-03-18 16:33:06.254906000 -0500
> +++ lxc/src/lxc/stop.c	2012-03-18 17:53:49.638230102 -0500
> @@ -40,7 +40,7 @@
>
>   lxc_log_define(lxc_stop, lxc);
>
> -int lxc_stop(const char *name)
> +int lxc_stop(const char *name, int shutdown, int timeout)
>   {
>   	struct lxc_command command = {
>   		.request = { .type = LXC_COMMAND_STOP },
> @@ -48,9 +48,30 @@
>
>   	int ret, stopped = 0;
>
> +	if (shutdown) {
> +		int pid = get_init_pid(name);
> +		if (pid == -1) {
> +			INFO("'%s' is already stopped", name);
> +			return 0;
> +		}
> +		ret = kill(pid, SIGPWR);
> +		if (ret<  0) {
> +			ERROR("failed to send SIGPWR");
> +			return -1;
> +		}
> +		if (timeout<  0)
> +			goto out;
> +		while (timeout-->  0) {
> +			lxc_state_t state = lxc_getstate(name);
> +			if (state == STOPPED)
> +				goto out;
> +			sleep(1);
> +		}
> +	}
>   	ret = lxc_command(name,&command,&stopped);
>   	if (ret<  0&&  stopped) {
> -		INFO("'%s' is already stopped", name);
> +		if (!shutdown)
> +			INFO("'%s' is already stopped", name);
>   		return 0;
>   	}
>
> @@ -68,6 +89,8 @@
>   		return -1;
>   	}
>
> +out:
> +
>   	INFO("'%s' has stopped", name);
>
>   	return 0;
> Index: lxc/src/lxc/lxc.h
> ===================================================================
> --- lxc.orig/src/lxc/lxc.h	2012-03-16 21:39:54.517075000 -0500
> +++ lxc/src/lxc/lxc.h	2012-03-18 16:42:23.336975492 -0500
> @@ -52,9 +52,12 @@
>    * Stop the container previously started with lxc_start, all
>    * the processes running inside this container will be killed.
>    * @name : the name of the container
> + * @shutdown : 1 if SIGPWR should be sent, 0 if SIGKILL
> + * @timeout : if not -1, wait this many seconds after sending
> + * SIGPWR before sending SIGKILL.
>    * Returns 0 on success,<  0 otherwise
>    */
> -extern int lxc_stop(const char *name);
> +extern int lxc_stop(const char *name, int shutdown, int timeout);
>
>   /*
>    * Open the monitoring mechanism for a specific container





More information about the lxc-users mailing list