[CRIU] [PATCH 2/2] utils: Make call_in_child_process() use parent's stack

Kirill Tkhai ktkhai at virtuozzo.com
Wed May 17 07:37:13 PDT 2017


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 at virtuozzo.com>
---
 criu/util.c |   43 ++++++++++++-------------------------------
 1 file changed, 12 insertions(+), 31 deletions(-)

diff --git a/criu/util.c b/criu/util.c
index 90473c09e..2e33ccf6a 100644
--- a/criu/util.c
+++ b/criu/util.c
@@ -47,6 +47,7 @@
 #include "namespaces.h"
 #include "criu-log.h"
 
+#include "clone-noasan.h"
 #include "cr_options.h"
 #include "servicefd.h"
 #include "cr-service.h"
@@ -1369,50 +1370,30 @@ int open_fd_of_real_pid(pid_t pid, int fd, int flags)
 
 int call_in_child_process(int (*fn)(void *), void *arg)
 {
-	sigset_t blockmask, oldmask;
-	int size, status, ret = -1;
-	char *stack;
+	int status, ret = -1;
 	pid_t pid;
-
-	size = 2 * 1024 * 1024; /* 2Mb */
-	stack = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
-	if (stack == MAP_FAILED) {
-		pr_perror("Can't allocate stack");
-		return -1;
-	}
-
-	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);
+	/*
+	 * Parent freezes till child exit, so child may use the same stack.
+	 * No SIGCHLD flag, so it's not need to block signal.
+	 */
+	pid = clone_noasan(fn, CLONE_VFORK | CLONE_VM | CLONE_FILES |
+			   CLONE_IO | CLONE_SIGHAND | CLONE_SYSVSEM, arg);
 	if (pid == -1) {
 		pr_perror("Can't clone");
-		goto out_unblock;
+		return -1;
 	}
 	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);
-		goto out_close;
+		goto out;
 	}
 	ret = 0;
-out_close:
 	/*
 	 * 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.
 	 */
+out:
 	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;
 }
 



More information about the CRIU mailing list