mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-07-27 16:18:16 +00:00
serialize multiple threads doing lxcapi_start()
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@oracle.com> Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
This commit is contained in:
parent
304143a823
commit
714540763b
@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
|
#include <pthread.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
@ -37,6 +38,8 @@
|
|||||||
#include <lxc/utils.h>
|
#include <lxc/utils.h>
|
||||||
#include <lxc/monitor.h>
|
#include <lxc/monitor.h>
|
||||||
|
|
||||||
|
static pthread_mutex_t thread_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
/* Define unshare() if missing from the C library */
|
/* Define unshare() if missing from the C library */
|
||||||
/* this is also in attach.c and lxccontainer.c: commonize it in utils.c */
|
/* this is also in attach.c and lxccontainer.c: commonize it in utils.c */
|
||||||
#ifndef HAVE_UNSHARE
|
#ifndef HAVE_UNSHARE
|
||||||
@ -58,6 +61,7 @@ lxc_log_define(lxc_container, lxc);
|
|||||||
/* LOCKING
|
/* LOCKING
|
||||||
* c->privlock protects the struct lxc_container from multiple threads.
|
* c->privlock protects the struct lxc_container from multiple threads.
|
||||||
* c->slock protects the on-disk container data
|
* 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
|
* NOTHING mutexes two independent programs with their own struct
|
||||||
* lxc_container for the same c->name, between API calls. For instance,
|
* lxc_container for the same c->name, between API calls. For instance,
|
||||||
* c->config_read(); c->start(); Between those calls, data on disk
|
* 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))
|
if (!lxc_container_get(c))
|
||||||
return false;
|
return false;
|
||||||
lxc_monitord_spawn(c->config_path);
|
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();
|
pid_t pid = fork();
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
lxc_container_put(c);
|
lxc_container_put(c);
|
||||||
|
pthread_mutex_unlock(&thread_mutex);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (pid != 0)
|
if (pid != 0) {
|
||||||
return wait_on_daemonized_start(c);
|
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 */
|
/* second fork to be reparented by init */
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
|
Loading…
Reference in New Issue
Block a user