[lxc-devel] [PATCH] serialize multiple threads doing lxcapi_start()

Dwight Engen dwight.engen at oracle.com
Mon May 13 16:03:14 UTC 2013


The problem is that the fd table is shared between threads and if a thread
forks() while another thread has an open fd to the monitor, the duped fd
in the fork()ed child will not get closed, thus causing monitord to stay
around since it thinks it still has a client. This only happened when
calling lxcapi_start() in the daemonized case since that is the only time
we try to get the status from the monitor.

Signed-off-by: Dwight Engen <dwight.engen at oracle.com>
---
 src/lxc/lxccontainer.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 04a9208..bac94c2 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -18,6 +18,7 @@
  */
 
 #define _GNU_SOURCE
+#include <pthread.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/wait.h>
@@ -37,6 +38,8 @@
 #include <lxc/utils.h>
 #include <lxc/monitor.h>
 
+static pthread_mutex_t thread_mutex = PTHREAD_MUTEX_INITIALIZER;
+
 /* Define unshare() if missing from the C library */
 /* this is also in attach.c and lxccontainer.c: commonize it in utils.c */
 #ifndef HAVE_UNSHARE
@@ -58,6 +61,7 @@ lxc_log_define(lxc_container, lxc);
 /* LOCKING
  * c->privlock protects the struct lxc_container from multiple threads.
  * c->slock protects the on-disk container data
+ * thread_mutex protects process data (ex: fd table) from multiple threads
  * NOTHING mutexes two independent programs with their own struct
  * lxc_container for the same c->name, between API calls.  For instance,
  * c->config_read(); c->start();  Between those calls, data on disk
@@ -391,13 +395,24 @@ static bool lxcapi_start(struct lxc_container *c, int useinit, char * const argv
 		if (!lxc_container_get(c))
 			return false;
 		lxc_monitord_spawn(c->config_path);
+
+		ret = pthread_mutex_lock(&thread_mutex);
+		if (ret != 0) {
+			ERROR("pthread_mutex_lock returned:%d %s", ret, strerror(ret));
+			return false;
+		}
 		pid_t pid = fork();
 		if (pid < 0) {
 			lxc_container_put(c);
+			pthread_mutex_unlock(&thread_mutex);
 			return false;
 		}
-		if (pid != 0)
-			return wait_on_daemonized_start(c);
+		if (pid != 0) {
+			ret = wait_on_daemonized_start(c);
+			pthread_mutex_unlock(&thread_mutex);
+			return ret;
+		}
+		pthread_mutex_unlock(&thread_mutex);
 		/* second fork to be reparented by init */
 		pid = fork();
 		if (pid < 0) {
-- 
1.8.1.4





More information about the lxc-devel mailing list