[lxc-devel] [PATCH] set the monitor process title to something useful

Tycho Andersen tycho.andersen at canonical.com
Fri Jan 30 13:59:13 UTC 2015


On Fri, Jan 30, 2015 at 01:38:59PM +0000, Serge Hallyn wrote:
> Quoting Tycho Andersen (tycho.andersen at canonical.com):
> > Instead of having a parent process that's called whatever the caller of the
> > library is called, we instead set it to "[lxc monitor] <lxcpath> <container>"
> > 
> > Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
> > ---
> >  src/lxc/lxccontainer.c | 10 +++++++++
> >  src/lxc/utils.c        | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++
> >  src/lxc/utils.h        |  1 +
> >  3 files changed, 72 insertions(+)
> > 
> > diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
> > index 4da1627..1176a6f 100644
> > --- a/src/lxc/lxccontainer.c
> > +++ b/src/lxc/lxccontainer.c
> > @@ -598,6 +598,7 @@ static bool lxcapi_start(struct lxc_container *c, int useinit, char * const argv
> >  	* while container is running...
> >  	*/
> >  	if (daemonize) {
> > +		char title[2048];
> >  		lxc_monitord_spawn(c->config_path);
> >  
> >  		pid_t pid = fork();
> > @@ -612,6 +613,15 @@ static bool lxcapi_start(struct lxc_container *c, int useinit, char * const argv
> >  			return wait_on_daemonized_start(c, pid);
> >  		}
> >  
> > +		/* We don't really care if this doesn't print all the
> > +		 * characters; all that it means is that the proctitle will be
> > +		 * ugly. Similarly, we also don't care if setproctitle()
> > +		 * fails. */
> > +
> > +		snprintf(title, sizeof(title), "[lxc monitor] %s %s", c->config_path, c->name);
> > +		INFO("Attempting to set proc title to %s", title);
> > +		setproctitle(title);
> > +
> >  		/* second fork to be reparented by init */
> >  		pid = fork();
> >  		if (pid < 0) {
> > diff --git a/src/lxc/utils.c b/src/lxc/utils.c
> > index 93de1c3..f517ee6 100644
> > --- a/src/lxc/utils.c
> > +++ b/src/lxc/utils.c
> > @@ -39,6 +39,7 @@
> >  #include <sys/types.h>
> >  #include <sys/wait.h>
> >  #include <assert.h>
> > +#include <sys/prctl.h>
> >  
> >  #include "utils.h"
> >  #include "log.h"
> > @@ -1540,3 +1541,63 @@ char *get_template_path(const char *t)
> >  
> >  	return tpath;
> >  }
> > +
> > +/*
> > + * Sets the process title to the specified title. Note:
> > + *   1. this function requires root to succeed
> > + *   2. it clears /proc/self/environ
> > + *   3. it may not succed (e.g. if title is longer than /proc/self/environ +
> > + *      the original title)
> > + */
> > +int setproctitle(char *title)
> > +{
> > +	char buf[2048], *tmp;
> > +	FILE *f;
> > +	int i, len, ret = 0;
> > +	unsigned long arg_start, arg_end, env_start, env_end;
> > +
> > +	f = fopen_cloexec("/proc/self/stat", "r");
> > +	if (!f) {
> > +		return -1;
> > +	}
> > +
> > +	tmp = fgets(buf, sizeof(buf), f);
> > +	fclose(f);
> > +	if (!tmp) {
> > +		return -1;
> > +	}
> > +
> > +	/* Skip the first 47 fields, column 48-51 are ARG_START and
> > +	 * ARG_END. */
> > +	tmp = strchr(buf, ' ');
> > +	for (i = 0; i < 46; i++)
> > +		tmp = strchr(tmp+1, ' ');
> 
> Could you add a check here at each step for tmp != NULL?  Or just
> 
> 	for (i = 0; i < 46 && tmp; i++)
> 		tmp = strchr(tmp+1, ' ');
> 	if (!tmp)
> 		return -1;

Yep, here's a few other changes as well.

Tycho


>From 6af924ded6e4ca9f0826a50c73cfcc8715159b18 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Fri, 30 Jan 2015 14:14:51 +0100
Subject: [PATCH] set the monitor process title to something useful

Instead of having a parent process that's called whatever the caller of the
library is called, we instead set it to "[lxc monitor] <lxcpath> <container>"

Closes #180

v2: check for null in tok for loop, only truncate environment when necessary

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/lxccontainer.c |  9 +++++++
 src/lxc/utils.c        | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/lxc/utils.h        |  1 +
 3 files changed, 77 insertions(+)

diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 4da1627..e02ee93 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -598,6 +598,7 @@ static bool lxcapi_start(struct lxc_container *c, int useinit, char * const argv
 	* while container is running...
 	*/
 	if (daemonize) {
+		char title[2048];
 		lxc_monitord_spawn(c->config_path);
 
 		pid_t pid = fork();
@@ -612,6 +613,14 @@ static bool lxcapi_start(struct lxc_container *c, int useinit, char * const argv
 			return wait_on_daemonized_start(c, pid);
 		}
 
+		/* We don't really care if this doesn't print all the
+		 * characters; all that it means is that the proctitle will be
+		 * ugly. Similarly, we also don't care if setproctitle()
+		 * fails. */
+		snprintf(title, sizeof(title), "[lxc monitor] %s %s", c->config_path, c->name);
+		INFO("Attempting to set proc title to %s", title);
+		setproctitle(title);
+
 		/* second fork to be reparented by init */
 		pid = fork();
 		if (pid < 0) {
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 93de1c3..9acf7e6 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -39,6 +39,7 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <assert.h>
+#include <sys/prctl.h>
 
 #include "utils.h"
 #include "log.h"
@@ -1540,3 +1541,69 @@ char *get_template_path(const char *t)
 
 	return tpath;
 }
+
+/*
+ * Sets the process title to the specified title. Note:
+ *   1. this function requires root to succeed
+ *   2. it clears /proc/self/environ
+ *   3. it may not succed (e.g. if title is longer than /proc/self/environ +
+ *      the original title)
+ */
+int setproctitle(char *title)
+{
+	char buf[2048], *tmp;
+	FILE *f;
+	int i, len, ret = 0;
+	unsigned long arg_start, arg_end, env_start, env_end;
+
+	f = fopen_cloexec("/proc/self/stat", "r");
+	if (!f) {
+		return -1;
+	}
+
+	tmp = fgets(buf, sizeof(buf), f);
+	fclose(f);
+	if (!tmp) {
+		return -1;
+	}
+
+	/* Skip the first 47 fields, column 48-51 are ARG_START and
+	 * ARG_END. */
+	tmp = strchr(buf, ' ');
+	for (i = 0; i < 46; i++) {
+		if (!tmp)
+			return -1;
+		tmp = strchr(tmp+1, ' ');
+	}
+
+	i = sscanf(tmp, "%lu %lu %lu %lu", &arg_start, &arg_end, &env_start, &env_end);
+	if (i != 4) {
+		return -1;
+	}
+
+	/* We're truncating the environment, so we should use at most the
+	 * length of the argument + environment for the title. */
+	len = strlen(title);
+	if (len > env_end - arg_start) {
+		arg_end = env_end;
+		len = env_end - arg_start;
+	} else {
+		/* Only truncate the environment if we're actually going to
+		 * overwrite part of it. */
+		if (len >= arg_end - arg_start) {
+			env_start = env_end;
+		}
+		arg_end = arg_start + len;
+	}
+
+
+	/* memcpy instead of strcpy since this isn't null terminated */
+	memcpy((void*)arg_start, title, len);
+
+	ret |= prctl(PR_SET_MM, PR_SET_MM_ARG_START,   (long)arg_start, 0, 0);
+	ret |= prctl(PR_SET_MM, PR_SET_MM_ARG_END,     (long)arg_end, 0, 0);
+	ret |= prctl(PR_SET_MM, PR_SET_MM_ENV_START,   (long)env_start, 0, 0);
+	ret |= prctl(PR_SET_MM, PR_SET_MM_ENV_END,     (long)env_end, 0, 0);
+
+	return ret;
+}
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index b23cd8e..cc18906 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -286,3 +286,4 @@ int print_to_file(const char *file, const char *content);
 bool switch_to_ns(pid_t pid, const char *ns);
 int is_dir(const char *path);
 char *get_template_path(const char *t);
+int setproctitle(char *title);
-- 
2.1.0



More information about the lxc-devel mailing list