I met a problem that container blocked by seteuid/setegid which is call in lxcContainerSetID on UP system and libvirt compiled with --with-fuse=yes. I looked into the glibc's codes, and found setxid in glibc calls futex() to wait for other threads to change their setxid_futex to 0(see setxid_mark_thread in glibc). since the process created by clone system call will not share the memory with the other threads and the context of memory doesn't changed until we call execl.(COW) So if the process which created by clone is called before fuse thread being stated, the new setxid_futex of fuse thread will not be saw in this process, it will be blocked forever. Maybe this problem should be fixed in glibc, but I send this patch as a quick fix. Signed-off-by: Gao feng <gaofeng@xxxxxxxxxxxxxx> --- src/lxc/lxc_controller.c | 13 ++++++++++++- src/lxc/lxc_fuse.c | 6 +++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index c8f68c0..ed83bb3 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -1977,7 +1977,18 @@ cleanup: static int virLXCControllerSetupFuse(virLXCControllerPtr ctrl) { - return lxcSetupFuse(&ctrl->fuse, ctrl->def); + int ret = lxcSetupFuse(&ctrl->fuse, ctrl->def); + + if (!ret) { + /* Wait for fuse thread starting run, so we + * can make sure the setxid_futex of fuse thread + * is 0(see start_thread of glibc), otherwise + * the lxcContainerChild will block at setxid. */ + virMutexLock(&ctrl->fuse->lock); + virMutexUnlock(&ctrl->fuse->lock); + } + + return ret; } static int diff --git a/src/lxc/lxc_fuse.c b/src/lxc/lxc_fuse.c index 9d12832..8cddfa8 100644 --- a/src/lxc/lxc_fuse.c +++ b/src/lxc/lxc_fuse.c @@ -272,6 +272,8 @@ static void lxcFuseDestroy(virLXCFusePtr fuse) static void lxcFuseRun(void *opaque) { virLXCFusePtr fuse = opaque; + /* Let libvirt_lxc continue. */ + virMutexUnlock(&fuse->lock); if (fuse_loop(fuse->fuse) < 0) virReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -321,7 +323,9 @@ int lxcSetupFuse(virLXCFusePtr *f, virDomainDefPtr def) fuse_unmount(fuse->mountpoint, fuse->ch); goto cleanup1; } - + /* Get mutex lock, lxcFuseRun will unlock it. this will + * cause libvirt_lxc wait for the fuse thread starting. */ + virMutexLock(&fuse->lock); if (virThreadCreate(&fuse->thread, false, lxcFuseRun, (void *)fuse) < 0) { lxcFuseDestroy(fuse); -- 1.8.3.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list