[lxc-devel] [PATCH 4/8] Add attach support to container C API

Serge Hallyn serge.hallyn at ubuntu.com
Wed Aug 14 20:33:42 UTC 2013


Quoting Christian Seiler (christian at iwakd.de):
> Signed-off-by: Christian Seiler <christian at iwakd.de>

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

> ---
>  src/lxc/lxccontainer.c |  124 ++++++++++++++++++++++++++++--------------------
>  src/lxc/lxccontainer.h |    8 +++-
>  2 files changed, 80 insertions(+), 52 deletions(-)
> 
> diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
> index 3affe22..1c77b63 100644
> --- a/src/lxc/lxccontainer.c
> +++ b/src/lxc/lxccontainer.c
> @@ -18,6 +18,7 @@
>   */
>  
>  #define _GNU_SOURCE
> +#include <stdarg.h>
>  #include <pthread.h>
>  #include <unistd.h>
>  #include <sys/types.h>
> @@ -38,6 +39,7 @@
>  #include "log.h"
>  #include "bdev.h"
>  #include "utils.h"
> +#include "attach.h"
>  #include <lxc/utils.h>
>  #include <lxc/monitor.h>
>  #include <sched.h>
> @@ -583,51 +585,30 @@ reboot:
>  static bool lxcapi_startl(struct lxc_container *c, int useinit, ...)
>  {
>  	va_list ap;
> -	char **inargs = NULL, **temp;
> -	int n_inargs = 0;
> +	char **inargs = NULL;
>  	bool bret = false;
>  
>  	/* container exists */
>  	if (!c)
>  		return false;
>  
> -	/* build array of arguments if any */
>  	va_start(ap, useinit);
> -	while (1) {
> -		char *arg;
> -		arg = va_arg(ap, char *);
> -		if (!arg)
> -			break;
> -		n_inargs++;
> -		temp = realloc(inargs, n_inargs * sizeof(*inargs));
> -		if (!temp) {
> -			va_end(ap);
> -			goto out;
> -		}
> -		inargs = temp;
> -		inargs[n_inargs - 1] = strdup(arg);  // not sure if it's safe not to copy
> -	}
> +	inargs = lxc_va_arg_list_to_argv(ap, 0, 1);
>  	va_end(ap);
>  
> -	/* add trailing NULL */
> -	if (n_inargs) {
> -		n_inargs++;
> -		temp = realloc(inargs, n_inargs * sizeof(*inargs));
> -		if (!temp)
> -			goto out;
> -		inargs = temp;
> -		inargs[n_inargs - 1] = NULL;
> +	if (!inargs) {
> +		ERROR("Memory allocation error.");
> +		goto out;
>  	}
>  
> -	bret = lxcapi_start(c, useinit, inargs);
> +	/* pass NULL if no arguments were supplied */
> +	bret = lxcapi_start(c, useinit, *inargs ? inargs : NULL);
>  
>  out:
>  	if (inargs) {
> -		int i;
> -		for (i = 0; i < n_inargs; i++) {
> -			if (inargs[i])
> -				free(inargs[i]);
> -		}
> +		char *arg;
> +		for (arg = *inargs; arg; arg++)
> +			free(arg);
>  		free(inargs);
>  	}
>  
> @@ -1133,9 +1114,8 @@ static bool lxcapi_createl(struct lxc_container *c, const char *t,
>  		const char *bdevtype, struct bdev_specs *specs, int flags, ...)
>  {
>  	bool bret = false;
> -	char **args = NULL, **temp;
> +	char **args = NULL;
>  	va_list ap;
> -	int nargs = 0;
>  
>  	if (!c)
>  		return false;
> @@ -1145,29 +1125,17 @@ static bool lxcapi_createl(struct lxc_container *c, const char *t,
>  	 * need to get a copy of the arguments.
>  	 */
>  	va_start(ap, flags);
> -	while (1) {
> -		char *arg;
> -		arg = va_arg(ap, char *);
> -		if (!arg)
> -			break;
> -		nargs++;
> -		temp = realloc(args, (nargs+1) * sizeof(*args));
> -		if (!temp) {
> -			va_end(ap);
> -			goto out;
> -		}
> -		args = temp;
> -		args[nargs - 1] = arg;
> -	}
> +	args = lxc_va_arg_list_to_argv(ap, 0, 0);
>  	va_end(ap);
> -	if (args)
> -		args[nargs] = NULL;
> +	if (!args) {
> +		ERROR("Memory allocation error.");
> +		goto out;
> +	}
>  
>  	bret = c->create(c, t, bdevtype, specs, flags, args);
>  
>  out:
> -	if (args)
> -		free(args);
> +	free(args);
>  	return bret;
>  }
>  
> @@ -2000,6 +1968,57 @@ out:
>  	return NULL;
>  }
>  
> +static int lxcapi_attach(struct lxc_container *c, lxc_attach_exec_t exec_function, void *exec_payload, lxc_attach_options_t *options, pid_t *attached_process)
> +{
> +	if (!c)
> +		return -1;
> +
> +	return lxc_attach(c->name, c->config_path, exec_function, exec_payload, options, attached_process);
> +}
> +
> +static int lxcapi_attach_run_wait(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char * const argv[])
> +{
> +	lxc_attach_command_t command;
> +	pid_t pid;
> +	int r;
> +
> +	if (!c)
> +		return -1;
> +
> +	command.program = (char*)program;
> +	command.argv = (char**)argv;
> +	r = lxc_attach(c->name, c->config_path, lxc_attach_run_command, &command, options, &pid);
> +	if (r < 0) {
> +		ERROR("ups");
> +		return r;
> +	}
> +	return lxc_wait_for_pid_status(pid);
> +}
> +
> +static int lxcapi_attach_run_waitl(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char *arg, ...)
> +{
> +	va_list ap;
> +	const char **argv;
> +	int ret;
> +
> +	if (!c)
> +		return -1;
> +
> +	va_start(ap, arg);
> +	argv = lxc_va_arg_list_to_argv_const(ap, 1);
> +	va_end(ap);
> +
> +	if (!argv) {
> +		ERROR("Memory allocation error.");
> +		return -1;
> +	}
> +	argv[0] = arg;
> +
> +	ret = lxcapi_attach_run_wait(c, options, program, (const char * const *)argv);
> +	free((void*)argv);
> +	return ret;
> +}
> +
>  struct lxc_container *lxc_container_new(const char *name, const char *configpath)
>  {
>  	struct lxc_container *c;
> @@ -2086,6 +2105,9 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
>  	c->set_config_path = lxcapi_set_config_path;
>  	c->clone = lxcapi_clone;
>  	c->get_ips = lxcapi_get_ips;
> +	c->attach = lxcapi_attach;
> +	c->attach_run_wait = lxcapi_attach_run_wait;
> +	c->attach_run_waitl = lxcapi_attach_run_waitl;
>  
>  	/* we'll allow the caller to update these later */
>  	if (lxc_log_init(NULL, "none", NULL, "lxc_container", 0, c->config_path)) {
> diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h
> index 3399c7f..e0c465c 100644
> --- a/src/lxc/lxccontainer.h
> +++ b/src/lxc/lxccontainer.h
> @@ -1,6 +1,7 @@
>  #ifndef __LXC_CONTAINER_H
>  #define __LXC_CONTAINER_H
>  #include "lxclock.h"
> +#include "attach_options.h"
>  #include <stdlib.h>
>  #include <malloc.h>
>  
> @@ -150,12 +151,17 @@ struct lxc_container {
>  	int (*console)(struct lxc_container *c, int ttynum,
>  		       int stdinfd, int stdoutfd, int stderrfd, int escape);
>  
> +	/* create subprocess and attach it to the container, run exec_function inside */
> +	int (*attach)(struct lxc_container *c, lxc_attach_exec_t exec_function, void *exec_payload, lxc_attach_options_t *options, pid_t *attached_process);
> +
> +	/* run program in container, wait for it to exit */
> +	int (*attach_run_wait)(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char * const argv[]);
> +	int (*attach_run_waitl)(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char *arg, ...);
>  #if 0
>  	bool (*commit_cgroups)(struct lxc_container *c);
>  	bool (*reread_cgroups)(struct lxc_container *c);
>  	// question with clone: how do we handle non-standard config file in orig?
>  	struct lxc_container (*clone)(struct container *c);
> -	int (*ns_attach)(struct lxc_container *c, int ns_mask);
>  	// we'll need some plumbing to support lxc-console
>  #endif
>  };
> -- 
> 1.7.10.4
> 
> 
> ------------------------------------------------------------------------------
> Get 100% visibility into Java/.NET code with AppDynamics Lite!
> It's a free troubleshooting tool designed for production.
> Get down to code-level detail for bottlenecks, with <2% overhead. 
> Download for free and get started troubleshooting in minutes. 
> http://pubads.g.doubleclick.net/gampad/clk?id=48897031&iu=/4140/ostg.clktrk
> _______________________________________________
> Lxc-devel mailing list
> Lxc-devel at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/lxc-devel




More information about the lxc-devel mailing list