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:
parent
0315082e06
commit
522d9c7180
43
criu/util.c
43
criu/util.c
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user