[lxc-devel] [PATCH] start: Detect early failure of the new child

Serge Hallyn serge.hallyn at ubuntu.com
Wed Apr 17 13:06:33 UTC 2013


Quoting Richard Weinberger (richard at nod.at):
> If the process in the new namespace dies very early
> we have currently no chance to detect this.
> The parent process will just die due to SIGPIPE
> if it write to the fd used for synchronisation and
> nobody will notice the real cause of the problem.
> 
> Install a SIGCHLD handler to detect the death.
> Later when the child does execve() to the init within
> the new namespace the handler will be disabled automatically.
> 
> Signed-off-by: Richard Weinberger <richard at nod.at>

Acked-by: Serge E. Hallyn <serge.hallyn at ubuntu.com>

Thanks Richard, useful for debugging.  It also might help (as a
follow-on patch) to use waitpid and print the exited pid alongside
the init pid.

> ---
>  src/lxc/start.c | 28 ++++++++++++++++++++++++++++
>  1 file changed, 28 insertions(+)
> 
> diff --git a/src/lxc/start.c b/src/lxc/start.c
> index aefccd6..a58737a 100644
> --- a/src/lxc/start.c
> +++ b/src/lxc/start.c
> @@ -198,6 +198,7 @@ static int setup_signal_fd(sigset_t *oldmask)
>  	    sigdelset(&mask, SIGILL) ||
>  	    sigdelset(&mask, SIGSEGV) ||
>  	    sigdelset(&mask, SIGBUS) ||
> +	    sigdelset(&mask, SIGCHLD) ||
>  	    sigprocmask(SIG_BLOCK, &mask, oldmask)) {
>  		SYSERROR("failed to set signal mask");
>  		return -1;
> @@ -739,10 +740,29 @@ int save_phys_nics(struct lxc_conf *conf)
>  	return 0;
>  }
>  
> +static void sigchild_handler(int sig)
> +{
> +	int status;
> +	pid_t child;
> +
> +	child = wait(&status);
> +	if (child < 0) {
> +		SYSERROR("SIGCHLD caught but wait() failed: %m\n");
> +		return;
> +	}
> +
> +	if (WIFSIGNALED(status))
> +		ERROR("Process in the new namespace died before execve()"
> +		      " due to signal: %i", WTERMSIG(status));
> +	else if (WIFEXITED(status))
> +		ERROR("Process in the new namespace died before execve()"
> +		      " with exit code: %i", WIFEXITED(status));
> +}
>  
>  int lxc_spawn(struct lxc_handler *handler)
>  {
>  	int failed_before_rename = 0;
> +	struct sigaction act;
>  	const char *name = handler->name;
>  
>  	if (lxc_sync_init(handler))
> @@ -793,6 +813,14 @@ int lxc_spawn(struct lxc_handler *handler)
>  		goto out_delete_net;
>  	}
>  
> +	/*
> +	 * Install a SIGCHLD handler to detect the death of the new child between
> +	 * clone() and execve().
> +	 */
> +	memset(&act, 0, sizeof(act));
> +	act.sa_handler = sigchild_handler;
> +	sigaction(SIGCHLD, &act, NULL);
> +
>  	/* Create a process in a new set of namespaces */
>  	handler->pid = lxc_clone(do_start, handler, handler->clone_flags);
>  	if (handler->pid < 0) {
> -- 
> 1.8.1.4
> 




More information about the lxc-devel mailing list