2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-29 13:28:27 +00:00

utils: Make call_in_child_process() use parent's stack

1)Use CLONE_VFORK to create subprocess, as it's safe after patch
"clone_noasan: Allow to create CLONE_VM|CLONE_VFORK processe".

2)add more CLONE_XXX to flags to speedup the syscall.

3)Do not send SIGCHLD, as parent sees child's exit() synchronuos anyway.

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This commit is contained in:
Kirill Tkhai 2017-05-17 17:37:13 +03:00 committed by Andrei Vagin
parent 0315082e06
commit 522d9c7180

View File

@ -47,6 +47,7 @@
#include "namespaces.h" #include "namespaces.h"
#include "criu-log.h" #include "criu-log.h"
#include "clone-noasan.h"
#include "cr_options.h" #include "cr_options.h"
#include "servicefd.h" #include "servicefd.h"
#include "cr-service.h" #include "cr-service.h"
@ -1423,50 +1424,30 @@ int open_fd_of_real_pid(pid_t pid, int fd, int flags)
int call_in_child_process(int (*fn)(void *), void *arg) int call_in_child_process(int (*fn)(void *), void *arg)
{ {
sigset_t blockmask, oldmask; int status, ret = -1;
int size, status, ret = -1;
char *stack;
pid_t pid; pid_t pid;
/*
size = 2 * 1024 * 1024; /* 2Mb */ * Parent freezes till child exit, so child may use the same stack.
stack = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); * No SIGCHLD flag, so it's not need to block signal.
if (stack == MAP_FAILED) { */
pr_perror("Can't allocate stack"); pid = clone_noasan(fn, CLONE_VFORK | CLONE_VM | CLONE_FILES |
return -1; CLONE_IO | CLONE_SIGHAND | CLONE_SYSVSEM, arg);
}
sigemptyset(&blockmask);
sigaddset(&blockmask, SIGCHLD);
if (sigprocmask(SIG_BLOCK, &blockmask, &oldmask) == -1) {
pr_perror("Can not set mask of blocked signals");
goto out_munmap;
}
pid = clone(fn, stack + size, CLONE_VM | CLONE_FILES | SIGCHLD, arg);
if (pid == -1) { if (pid == -1) {
pr_perror("Can't clone"); pr_perror("Can't clone");
goto out_unblock; return -1;
} }
errno = 0; errno = 0;
if (waitpid(pid, &status, 0) != pid || !WIFEXITED(status) || WEXITSTATUS(status)) { if (waitpid(pid, &status, __WALL) != pid || !WIFEXITED(status) || WEXITSTATUS(status)) {
pr_err("Can't wait or bad status: errno=%d, status=%d", errno, status); pr_err("Can't wait or bad status: errno=%d, status=%d", errno, status);
goto out_close; goto out;
} }
ret = 0; ret = 0;
out_close:
/* /*
* Child opened PROC_SELF for pid. If we create one more child * Child opened PROC_SELF for pid. If we create one more child
* with the same pid later, it will try to reuse this /proc/self. * with the same pid later, it will try to reuse this /proc/self.
*/ */
out:
close_pid_proc(); close_pid_proc();
out_unblock:
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) == -1) {
pr_perror("Can not unset mask of blocked signals");
ret = -1;
}
out_munmap:
munmap(stack, size);
return ret; return ret;
} }