if (pid > 0)
return wait_for_pid(pid);
- process_unlock(); // we're no longer sharing
l = strlen(src) + 2;
s = malloc(l);
if (!s)
if (pid > 0)
return wait_for_pid(pid);
- process_unlock(); // we're no longer sharing
// If the file is not a block device, we don't want mkfs to ask
// us about whether to proceed.
close(0);
return ret;
}
- process_unlock(); // we're no longer sharing
if (unshare(CLONE_NEWNS) < 0)
exit(1);
if (!pid) {
char dev[MAXPATHLEN];
- process_unlock(); // we're no longer sharing
ret = snprintf(dev, MAXPATHLEN, "%s/%s", zfsroot, nname);
if (ret < 0 || ret >= MAXPATHLEN)
exit(1);
if ((pid = fork()) < 0)
return -1;
if (!pid) {
- process_unlock(); // we're no longer sharing
execlp("zfs", "zfs", "destroy", path1, NULL);
exit(1);
}
if ((pid = fork()) < 0)
return -1;
if (!pid) {
- process_unlock(); // we're no longer sharing
execlp("zfs", "zfs", "snapshot", path1, NULL);
exit(1);
}
if ((pid = fork()) < 0)
return -1;
if (!pid) {
- process_unlock(); // we're no longer sharing
execlp("zfs", "zfs", "clone", option, path1, path2, NULL);
exit(1);
}
if (pid)
return wait_for_pid(pid);
- process_unlock(); // we're no longer sharing
if (!zfs_list_entry(orig->src, output, MAXPATHLEN)) {
ERROR("Error: zfs entry for %s not found", orig->src);
return -1;
if (pid)
return wait_for_pid(pid);
- process_unlock(); // we're no longer sharing
char dev[MAXPATHLEN];
ret = snprintf(dev, MAXPATHLEN, "%s/%s", zfsroot, n);
if (ret < 0 || ret >= MAXPATHLEN)
if (pid > 0)
return wait_for_pid(pid);
- process_unlock(); // we're no longer sharing
// lvcreate default size is in M, not bytes.
ret = snprintf(sz, 24, "%lu", size/1000000);
if (ret < 0 || ret >= 24)
if (pid > 0)
return wait_for_pid(pid);
- process_unlock(); // we're no longer sharing
// lvcreate default size is in M, not bytes.
ret = snprintf(sz, 24, "%lu", size/1000000);
if (ret < 0 || ret >= 24)
if ((pid = fork()) < 0)
return -1;
if (!pid) {
- process_unlock(); // we're no longer sharing
execlp("lvremove", "lvremove", "-f", orig->src, NULL);
exit(1);
}
return new;
}
- process_unlock(); // we're no longer sharing
if (unshare(CLONE_NEWNS) < 0) {
SYSERROR("unshare CLONE_NEWNS");
exit(1);
if (pid != 0)
return wait_on_daemonized_start(c, pid);
- process_unlock(); // we're no longer sharing
/* second fork to be reparented by init */
pid = fork();
if (pid < 0) {
char **newargv;
struct lxc_conf *conf = c->lxc_conf;
- process_unlock(); // we're no longer sharing
if (quiet) {
close(0);
close(1);
if (pid == 0) { // child
struct bdev *bdev = NULL;
- process_unlock(); // we're no longer sharing
if (!(bdev = do_bdev_create(c, bdevtype, specs))) {
ERROR("Error creating backing store type %s for %s",
bdevtype ? bdevtype : "(none)", c->name);
if (pid > 0)
return wait_for_pid(pid);
- process_unlock(); // we're no longer sharing
bdev = bdev_init(c->lxc_conf->rootfs.path, c->lxc_conf->rootfs.mount, NULL);
if (!bdev)
exit(1);
int ret;
if ((ret = pthread_mutex_unlock(l)) != 0) {
- fprintf(stderr, "pthread_mutex_lock returned:%d %s", ret, strerror(ret));
+ fprintf(stderr, "pthread_mutex_unlock returned:%d %s", ret, strerror(ret));
dump_stacktrace();
exit(1);
}
unlock_mutex(&thread_mutex);
}
+/* One thread can do fork() while another one is holding a mutex.
+ * There is only one thread in child just after the fork(), so noone will ever release that mutex.
+ * We setup a "child" fork handler to unlock the mutex just after the fork().
+ * For several mutex types, unlocking an unlocked mutex can lead to undefined behavior.
+ * One way to deal with it is to setup "prepare" fork handler
+ * to lock the mutex before fork() and both "parent" and "child" fork handlers
+ * to unlock the mutex.
+ * This forbids doing fork() while explicitly holding the lock.
+ */
+__attribute__((constructor))
+static void process_lock_setup_atfork(void)
+{
+ pthread_atfork(process_lock, process_unlock, process_unlock);
+}
+
/* Protects static const values inside the lxc_global_config_value funtion */
void static_lock(void)
{
unlock_mutex(&static_mutex);
}
+__attribute__((constructor))
+static void static_lock_setup_atfork(void)
+{
+ pthread_atfork(static_lock, static_unlock, static_unlock);
+}
+
int container_mem_lock(struct lxc_container *c)
{
return lxclock(c->privlock, 0);