[07/10] zdtm/lib: add test_waitpre so that test knows about predump iters

Submitted by Pavel Tikhomirov on Feb. 22, 2018, 11:49 a.m.

Details

Message ID 20180222114928.24343-8-ptikhomirov@virtuozzo.com
State Accepted
Series "don't use wrong pagemap (from other task) on pid reuse"
Headers show

Commit Message

Pavel Tikhomirov Feb. 22, 2018, 11:49 a.m.
- anounce predump finish to a target process from predump loop in
zdtm.py
- propagate SIGUSR1 signal to real test process from ns_init for
ns and uns flavors.
- in ns_init also fix fd leak

So now test's main process can do:

while (!test_waitpre()) {
	/* do something after predump */
}
/* do something after restore */

All test_waitsig and test_go still work the same as before.

https://jira.sw.ru/browse/PSBM-67502

Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
---
 test/zdtm.py            |  8 ++++++++
 test/zdtm/lib/ns.c      | 46 ++++++++++++++++++++++++++++------------------
 test/zdtm/lib/ns.h      |  6 ++++++
 test/zdtm/lib/test.c    | 30 +++++++++++++++++++++++++-----
 test/zdtm/lib/zdtmtst.h |  1 +
 5 files changed, 68 insertions(+), 23 deletions(-)

Patch hide | download patch | download mbox

diff --git a/test/zdtm.py b/test/zdtm.py
index 030065dde..1f9b9fc9a 100755
--- a/test/zdtm.py
+++ b/test/zdtm.py
@@ -459,6 +459,13 @@  flavors = {'h': host_flavor, 'ns': ns_flavor, 'uns': userns_flavor}
 
 		self.__flavor.fini()
 
+	def signal_pre_dump(self):
+		if self.__pid == 0:
+			self.getpid()
+		sig = signal.SIGUSR1
+		print "Send the %d signal to  %s" % (sig, self.__pid)
+		os.kill(int(self.__pid), sig)
+
 	def stop(self):
 		self.__freezer.thaw()
 		self.getpid()  # Read the pid from pidfile back
@@ -1208,6 +1215,7 @@  do_sbs = False
 			else:
 				cr_api.dump("pre-dump")
 				try_run_hook(test, ["--post-pre-dump"])
+				test.signal_pre_dump()
 			time.sleep(pres[1])
 
 		sbs('pre-dump')
diff --git a/test/zdtm/lib/ns.c b/test/zdtm/lib/ns.c
index 7a0949f22..92922e928 100644
--- a/test/zdtm/lib/ns.c
+++ b/test/zdtm/lib/ns.c
@@ -168,9 +168,12 @@  static void ns_sig_hand(int signo)
 	char buf[128] = "";
 
 	if (signo == SIGTERM) {
-		futex_set_and_wake(&sig_received, signo);
+		futex_set_and_wake(&sig_received, TEST_SIG_STOP);
 		len = snprintf(buf, sizeof(buf), "Time to stop and check\n");
 		goto write_out;
+	} else if (signo == SIGUSR1) {
+		futex_cmpxchg_and_wake(&sig_received, TEST_NO_SIG, TEST_SIG_PRE);
+		return;
 	}
 
 	while (1) {
@@ -179,9 +182,9 @@  static void ns_sig_hand(int signo)
 			return;
 		if (pid == -1) {
 			if (errno == ECHILD) {
-				if (futex_get(&sig_received))
+				if (futex_get(&sig_received) == TEST_SIG_STOP)
 					return;
-				futex_set_and_wake(&sig_received, signo);
+				futex_set_and_wake(&sig_received, TEST_SIG_STOP);
 				len = snprintf(buf, sizeof(buf),
 						"All test processes exited\n");
 			} else {
@@ -235,7 +238,7 @@  int ns_init(int argc, char **argv)
 		.sa_handler	= ns_sig_hand,
 		.sa_flags	= SA_RESTART,
 	};
-	int ret, fd, status_pipe = STATUS_FD;
+	int ret, test_ret, fd, status_pipe = STATUS_FD;
 	char buf[128], *x;
 	pid_t pid;
 	bool reap;
@@ -258,6 +261,11 @@  int ns_init(int argc, char **argv)
 		exit(1);
 	}
 
+	if (sigaction(SIGUSR1, &sa, NULL)) {
+		fprintf(stderr, "Can't set SIGUSR1 handler: %m\n");
+		exit(1);
+	}
+
 	x = malloc(strlen(pidfile) + 3);
 	sprintf(x, "%sns", pidfile);
 	pidfile = x;
@@ -273,11 +281,11 @@  int ns_init(int argc, char **argv)
 		return 0; /* Continue normal test startup */
 	}
 
-	ret = -1;
-	if (waitpid(pid, &ret, 0) < 0)
+	test_ret = -1;
+	if (waitpid(pid, &test_ret, 0) < 0)
 		fprintf(stderr, "waitpid() failed: %m\n");
-	else if (ret)
-		fprintf(stderr, "The test returned non-zero code %d\n", ret);
+	else if (test_ret)
+		fprintf(stderr, "The test returned non-zero code %d\n", test_ret);
 
 	if (reap && sigaction(SIGCHLD, &sa, NULL)) {
 		fprintf(stderr, "Can't set SIGCHLD handler: %m\n");
@@ -298,15 +306,6 @@  int ns_init(int argc, char **argv)
 			fprintf(stderr, "%d return %d\n", pid, status);
 	}
 
-	/* Daemonize */
-	write(status_pipe, &ret, sizeof(ret));
-	close(status_pipe);
-	if (ret)
-		exit(ret);
-
-	/* suspend/resume */
-	test_waitsig();
-
 	fd = open(pidfile, O_RDONLY);
 	if (fd == -1) {
 		fprintf(stderr, "open(%s) failed: %m\n", pidfile);
@@ -314,12 +313,23 @@  int ns_init(int argc, char **argv)
 	}
 	ret = read(fd, buf, sizeof(buf) - 1);
 	buf[ret] = '\0';
+	close(fd);
 	if (ret == -1) {
 		fprintf(stderr, "read() failed: %m\n");
 		exit(1);
 	}
-
 	pid = atoi(buf);
+
+	/* Daemonize */
+	write(status_pipe, &test_ret, sizeof(test_ret));
+	close(status_pipe);
+	if (test_ret)
+		exit(test_ret);
+
+	while (!test_waitpre())
+		kill(pid, SIGUSR1);
+	/* after suspend/resume */
+
 	fprintf(stderr, "kill(%d, SIGTERM)\n", pid);
 	if (pid > 0)
 		kill(pid, SIGTERM);
diff --git a/test/zdtm/lib/ns.h b/test/zdtm/lib/ns.h
index 23378bc60..78395984e 100644
--- a/test/zdtm/lib/ns.h
+++ b/test/zdtm/lib/ns.h
@@ -12,4 +12,10 @@  extern int ns_init(int argc, char **argv);
 extern void test_waitsig(void);
 extern void parseargs(int, char **);
 
+enum {
+	TEST_NO_SIG = 0,
+	TEST_SIG_PRE,
+	TEST_SIG_STOP,
+};
+
 #endif
diff --git a/test/zdtm/lib/test.c b/test/zdtm/lib/test.c
index 6dce027f0..c16442196 100644
--- a/test/zdtm/lib/test.c
+++ b/test/zdtm/lib/test.c
@@ -35,9 +35,13 @@  static int parent;
 
 static void sig_hand(int signo)
 {
-	if (parent)
-		futex_set_and_wake(&test_shared_state->stage, TEST_FAIL_STAGE);
-	futex_set_and_wake(&sig_received, signo);
+	if (signo == SIGUSR1) {
+		futex_cmpxchg_and_wake(&sig_received, TEST_NO_SIG, TEST_SIG_PRE);
+	} else {
+		if (parent)
+			futex_set_and_wake(&test_shared_state->stage, TEST_FAIL_STAGE);
+		futex_set_and_wake(&sig_received, TEST_SIG_STOP);
+	}
 }
 
 static char *outfile;
@@ -219,6 +223,11 @@  void test_init(int argc, char **argv)
 		exit(1);
 	}
 
+	if (sigaction(SIGUSR1, &sa, NULL)) {
+		fprintf(stderr, "Can't set SIGUSR1 handler: %m\n");
+		exit(1);
+	}
+
 	setup_outfile();
 	redir_stdfds();
 
@@ -289,12 +298,23 @@  void test_daemon()
 
 int test_go(void)
 {
-	return !futex_get(&sig_received);
+	return futex_get(&sig_received) != TEST_SIG_STOP;
 }
 
 void test_waitsig(void)
 {
-	futex_wait_while(&sig_received, 0);
+	futex_wait_until(&sig_received, TEST_SIG_STOP);
+}
+
+int test_waitpre(void)
+{
+	int ret;
+
+	futex_wait_while(&sig_received, TEST_NO_SIG);
+	ret = futex_cmpxchg_and_wake(&sig_received, TEST_SIG_PRE, TEST_NO_SIG);
+	if (ret == TEST_SIG_PRE)
+		return 0;
+	return 1;
 }
 
 pid_t sys_clone_unified(unsigned long flags, void *child_stack, void *parent_tid,
diff --git a/test/zdtm/lib/zdtmtst.h b/test/zdtm/lib/zdtmtst.h
index dbe825cbc..f7af6dc1b 100644
--- a/test/zdtm/lib/zdtmtst.h
+++ b/test/zdtm/lib/zdtmtst.h
@@ -41,6 +41,7 @@  extern void test_msg(const char *format, ...)
 extern int test_go(void);
 /* sleep until SIGTERM is delivered */
 extern void test_waitsig(void);
+extern int test_waitpre(void);
 
 #include <stdint.h>
 

Comments

Andrey Vagin Feb. 28, 2018, 11:59 p.m.
[root@fc24 criu]# python test/zdtm.py run -t zdtm/static/signalfd00 --remote-lazy-pages --pre 2
=== Run 1/1 ================ zdtm/static/signalfd00

======================= Run zdtm/static/signalfd00 in h ========================
Start test
./signalfd00 --pidfile=signalfd00.pid --outfile=signalfd00.out
Run criu pre-dump
Send the 10 signal to  36
Run criu pre-dump
Send the 10 signal to  36
Run criu dump
Run criu page-server
Run criu lazy-pages
Run criu restore
Send the 15 signal to  36
Wait for zdtm/static/signalfd00(36) to die for 0.100000
############### Test zdtm/static/signalfd00 FAIL at result check ###############
Test output: ================================
02:59:00.580:    36: FAIL: signalfd00.c:52: ghost signal (errno = 11 (Resource temporarily unavailable))

 <<< ================================
criu lazy-pages exited with -15
criu page-server exited with 0
##################################### FAIL #####################################


On Thu, Feb 22, 2018 at 02:49:25PM +0300, Pavel Tikhomirov wrote:
> - anounce predump finish to a target process from predump loop in
> zdtm.py
> - propagate SIGUSR1 signal to real test process from ns_init for
> ns and uns flavors.
> - in ns_init also fix fd leak
> 
> So now test's main process can do:
> 
> while (!test_waitpre()) {
> 	/* do something after predump */
> }
> /* do something after restore */
> 
> All test_waitsig and test_go still work the same as before.
> 
> https://jira.sw.ru/browse/PSBM-67502
> 
> Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
> ---
>  test/zdtm.py            |  8 ++++++++
>  test/zdtm/lib/ns.c      | 46 ++++++++++++++++++++++++++++------------------
>  test/zdtm/lib/ns.h      |  6 ++++++
>  test/zdtm/lib/test.c    | 30 +++++++++++++++++++++++++-----
>  test/zdtm/lib/zdtmtst.h |  1 +
>  5 files changed, 68 insertions(+), 23 deletions(-)
> 
> diff --git a/test/zdtm.py b/test/zdtm.py
> index 030065dde..1f9b9fc9a 100755
> --- a/test/zdtm.py
> +++ b/test/zdtm.py
> @@ -459,6 +459,13 @@ flavors = {'h': host_flavor, 'ns': ns_flavor, 'uns': userns_flavor}
>  
>  		self.__flavor.fini()
>  
> +	def signal_pre_dump(self):
> +		if self.__pid == 0:
> +			self.getpid()
> +		sig = signal.SIGUSR1
> +		print "Send the %d signal to  %s" % (sig, self.__pid)
> +		os.kill(int(self.__pid), sig)
> +
>  	def stop(self):
>  		self.__freezer.thaw()
>  		self.getpid()  # Read the pid from pidfile back
> @@ -1208,6 +1215,7 @@ do_sbs = False
>  			else:
>  				cr_api.dump("pre-dump")
>  				try_run_hook(test, ["--post-pre-dump"])
> +				test.signal_pre_dump()
>  			time.sleep(pres[1])
>  
>  		sbs('pre-dump')
> diff --git a/test/zdtm/lib/ns.c b/test/zdtm/lib/ns.c
> index 7a0949f22..92922e928 100644
> --- a/test/zdtm/lib/ns.c
> +++ b/test/zdtm/lib/ns.c
> @@ -168,9 +168,12 @@ static void ns_sig_hand(int signo)
>  	char buf[128] = "";
>  
>  	if (signo == SIGTERM) {
> -		futex_set_and_wake(&sig_received, signo);
> +		futex_set_and_wake(&sig_received, TEST_SIG_STOP);
>  		len = snprintf(buf, sizeof(buf), "Time to stop and check\n");
>  		goto write_out;
> +	} else if (signo == SIGUSR1) {
> +		futex_cmpxchg_and_wake(&sig_received, TEST_NO_SIG, TEST_SIG_PRE);
> +		return;
>  	}
>  
>  	while (1) {
> @@ -179,9 +182,9 @@ static void ns_sig_hand(int signo)
>  			return;
>  		if (pid == -1) {
>  			if (errno == ECHILD) {
> -				if (futex_get(&sig_received))
> +				if (futex_get(&sig_received) == TEST_SIG_STOP)
>  					return;
> -				futex_set_and_wake(&sig_received, signo);
> +				futex_set_and_wake(&sig_received, TEST_SIG_STOP);
>  				len = snprintf(buf, sizeof(buf),
>  						"All test processes exited\n");
>  			} else {
> @@ -235,7 +238,7 @@ int ns_init(int argc, char **argv)
>  		.sa_handler	= ns_sig_hand,
>  		.sa_flags	= SA_RESTART,
>  	};
> -	int ret, fd, status_pipe = STATUS_FD;
> +	int ret, test_ret, fd, status_pipe = STATUS_FD;
>  	char buf[128], *x;
>  	pid_t pid;
>  	bool reap;
> @@ -258,6 +261,11 @@ int ns_init(int argc, char **argv)
>  		exit(1);
>  	}
>  
> +	if (sigaction(SIGUSR1, &sa, NULL)) {
> +		fprintf(stderr, "Can't set SIGUSR1 handler: %m\n");
> +		exit(1);
> +	}
> +
>  	x = malloc(strlen(pidfile) + 3);
>  	sprintf(x, "%sns", pidfile);
>  	pidfile = x;
> @@ -273,11 +281,11 @@ int ns_init(int argc, char **argv)
>  		return 0; /* Continue normal test startup */
>  	}
>  
> -	ret = -1;
> -	if (waitpid(pid, &ret, 0) < 0)
> +	test_ret = -1;
> +	if (waitpid(pid, &test_ret, 0) < 0)
>  		fprintf(stderr, "waitpid() failed: %m\n");
> -	else if (ret)
> -		fprintf(stderr, "The test returned non-zero code %d\n", ret);
> +	else if (test_ret)
> +		fprintf(stderr, "The test returned non-zero code %d\n", test_ret);
>  
>  	if (reap && sigaction(SIGCHLD, &sa, NULL)) {
>  		fprintf(stderr, "Can't set SIGCHLD handler: %m\n");
> @@ -298,15 +306,6 @@ int ns_init(int argc, char **argv)
>  			fprintf(stderr, "%d return %d\n", pid, status);
>  	}
>  
> -	/* Daemonize */
> -	write(status_pipe, &ret, sizeof(ret));
> -	close(status_pipe);
> -	if (ret)
> -		exit(ret);
> -
> -	/* suspend/resume */
> -	test_waitsig();
> -
>  	fd = open(pidfile, O_RDONLY);
>  	if (fd == -1) {
>  		fprintf(stderr, "open(%s) failed: %m\n", pidfile);
> @@ -314,12 +313,23 @@ int ns_init(int argc, char **argv)
>  	}
>  	ret = read(fd, buf, sizeof(buf) - 1);
>  	buf[ret] = '\0';
> +	close(fd);
>  	if (ret == -1) {
>  		fprintf(stderr, "read() failed: %m\n");
>  		exit(1);
>  	}
> -
>  	pid = atoi(buf);
> +
> +	/* Daemonize */
> +	write(status_pipe, &test_ret, sizeof(test_ret));
> +	close(status_pipe);
> +	if (test_ret)
> +		exit(test_ret);
> +
> +	while (!test_waitpre())
> +		kill(pid, SIGUSR1);
> +	/* after suspend/resume */
> +
>  	fprintf(stderr, "kill(%d, SIGTERM)\n", pid);
>  	if (pid > 0)
>  		kill(pid, SIGTERM);
> diff --git a/test/zdtm/lib/ns.h b/test/zdtm/lib/ns.h
> index 23378bc60..78395984e 100644
> --- a/test/zdtm/lib/ns.h
> +++ b/test/zdtm/lib/ns.h
> @@ -12,4 +12,10 @@ extern int ns_init(int argc, char **argv);
>  extern void test_waitsig(void);
>  extern void parseargs(int, char **);
>  
> +enum {
> +	TEST_NO_SIG = 0,
> +	TEST_SIG_PRE,
> +	TEST_SIG_STOP,
> +};
> +
>  #endif
> diff --git a/test/zdtm/lib/test.c b/test/zdtm/lib/test.c
> index 6dce027f0..c16442196 100644
> --- a/test/zdtm/lib/test.c
> +++ b/test/zdtm/lib/test.c
> @@ -35,9 +35,13 @@ static int parent;
>  
>  static void sig_hand(int signo)
>  {
> -	if (parent)
> -		futex_set_and_wake(&test_shared_state->stage, TEST_FAIL_STAGE);
> -	futex_set_and_wake(&sig_received, signo);
> +	if (signo == SIGUSR1) {
> +		futex_cmpxchg_and_wake(&sig_received, TEST_NO_SIG, TEST_SIG_PRE);
> +	} else {
> +		if (parent)
> +			futex_set_and_wake(&test_shared_state->stage, TEST_FAIL_STAGE);
> +		futex_set_and_wake(&sig_received, TEST_SIG_STOP);
> +	}
>  }
>  
>  static char *outfile;
> @@ -219,6 +223,11 @@ void test_init(int argc, char **argv)
>  		exit(1);
>  	}
>  
> +	if (sigaction(SIGUSR1, &sa, NULL)) {
> +		fprintf(stderr, "Can't set SIGUSR1 handler: %m\n");
> +		exit(1);
> +	}
> +
>  	setup_outfile();
>  	redir_stdfds();
>  
> @@ -289,12 +298,23 @@ void test_daemon()
>  
>  int test_go(void)
>  {
> -	return !futex_get(&sig_received);
> +	return futex_get(&sig_received) != TEST_SIG_STOP;
>  }
>  
>  void test_waitsig(void)
>  {
> -	futex_wait_while(&sig_received, 0);
> +	futex_wait_until(&sig_received, TEST_SIG_STOP);
> +}
> +
> +int test_waitpre(void)
> +{
> +	int ret;
> +
> +	futex_wait_while(&sig_received, TEST_NO_SIG);
> +	ret = futex_cmpxchg_and_wake(&sig_received, TEST_SIG_PRE, TEST_NO_SIG);
> +	if (ret == TEST_SIG_PRE)
> +		return 0;
> +	return 1;
>  }
>  
>  pid_t sys_clone_unified(unsigned long flags, void *child_stack, void *parent_tid,
> diff --git a/test/zdtm/lib/zdtmtst.h b/test/zdtm/lib/zdtmtst.h
> index dbe825cbc..f7af6dc1b 100644
> --- a/test/zdtm/lib/zdtmtst.h
> +++ b/test/zdtm/lib/zdtmtst.h
> @@ -41,6 +41,7 @@ extern void test_msg(const char *format, ...)
>  extern int test_go(void);
>  /* sleep until SIGTERM is delivered */
>  extern void test_waitsig(void);
> +extern int test_waitpre(void);
>  
>  #include <stdint.h>
>  
> -- 
> 2.14.3
>
Andrey Vagin March 1, 2018, 12:43 a.m.
On Thu, Feb 22, 2018 at 02:49:25PM +0300, Pavel Tikhomirov wrote:
> - anounce predump finish to a target process from predump loop in
> zdtm.py
> - propagate SIGUSR1 signal to real test process from ns_init for
> ns and uns flavors.
> - in ns_init also fix fd leak

The whole scheme is racy, because you get notifications about pre-dump,
but you don't send notifications back after a test does post-pre-dump
actions.


And here is one comment bellow

> 
> So now test's main process can do:
> 
> while (!test_waitpre()) {
> 	/* do something after predump */
> }
> /* do something after restore */
> 
> All test_waitsig and test_go still work the same as before.
> 
> https://jira.sw.ru/browse/PSBM-67502
> 
> Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
> ---
>  test/zdtm.py            |  8 ++++++++
>  test/zdtm/lib/ns.c      | 46 ++++++++++++++++++++++++++++------------------
>  test/zdtm/lib/ns.h      |  6 ++++++
>  test/zdtm/lib/test.c    | 30 +++++++++++++++++++++++++-----
>  test/zdtm/lib/zdtmtst.h |  1 +
>  5 files changed, 68 insertions(+), 23 deletions(-)
> 
> diff --git a/test/zdtm.py b/test/zdtm.py
> index 030065dde..1f9b9fc9a 100755
> --- a/test/zdtm.py
> +++ b/test/zdtm.py
> @@ -459,6 +459,13 @@ flavors = {'h': host_flavor, 'ns': ns_flavor, 'uns': userns_flavor}
>  
>  		self.__flavor.fini()
>  
> +	def signal_pre_dump(self):
> +		if self.__pid == 0:
> +			self.getpid()
> +		sig = signal.SIGUSR1
> +		print "Send the %d signal to  %s" % (sig, self.__pid)
> +		os.kill(int(self.__pid), sig)
> +
>  	def stop(self):
>  		self.__freezer.thaw()
>  		self.getpid()  # Read the pid from pidfile back
> @@ -1208,6 +1215,7 @@ do_sbs = False
>  			else:
>  				cr_api.dump("pre-dump")
>  				try_run_hook(test, ["--post-pre-dump"])
> +				test.signal_pre_dump()
>  			time.sleep(pres[1])
>  
>  		sbs('pre-dump')
> diff --git a/test/zdtm/lib/ns.c b/test/zdtm/lib/ns.c
> index 7a0949f22..92922e928 100644
> --- a/test/zdtm/lib/ns.c
> +++ b/test/zdtm/lib/ns.c
> @@ -168,9 +168,12 @@ static void ns_sig_hand(int signo)
>  	char buf[128] = "";
>  
>  	if (signo == SIGTERM) {
> -		futex_set_and_wake(&sig_received, signo);
> +		futex_set_and_wake(&sig_received, TEST_SIG_STOP);
>  		len = snprintf(buf, sizeof(buf), "Time to stop and check\n");
>  		goto write_out;
> +	} else if (signo == SIGUSR1) {
> +		futex_cmpxchg_and_wake(&sig_received, TEST_NO_SIG, TEST_SIG_PRE);
> +		return;
>  	}
>  
>  	while (1) {
> @@ -179,9 +182,9 @@ static void ns_sig_hand(int signo)
>  			return;
>  		if (pid == -1) {
>  			if (errno == ECHILD) {
> -				if (futex_get(&sig_received))
> +				if (futex_get(&sig_received) == TEST_SIG_STOP)
>  					return;
> -				futex_set_and_wake(&sig_received, signo);
> +				futex_set_and_wake(&sig_received, TEST_SIG_STOP);
>  				len = snprintf(buf, sizeof(buf),
>  						"All test processes exited\n");
>  			} else {
> @@ -235,7 +238,7 @@ int ns_init(int argc, char **argv)
>  		.sa_handler	= ns_sig_hand,
>  		.sa_flags	= SA_RESTART,
>  	};
> -	int ret, fd, status_pipe = STATUS_FD;
> +	int ret, test_ret, fd, status_pipe = STATUS_FD;
>  	char buf[128], *x;
>  	pid_t pid;
>  	bool reap;
> @@ -258,6 +261,11 @@ int ns_init(int argc, char **argv)
>  		exit(1);
>  	}
>  
> +	if (sigaction(SIGUSR1, &sa, NULL)) {
> +		fprintf(stderr, "Can't set SIGUSR1 handler: %m\n");
> +		exit(1);
> +	}
> +
>  	x = malloc(strlen(pidfile) + 3);
>  	sprintf(x, "%sns", pidfile);
>  	pidfile = x;
> @@ -273,11 +281,11 @@ int ns_init(int argc, char **argv)
>  		return 0; /* Continue normal test startup */
>  	}
>  
> -	ret = -1;
> -	if (waitpid(pid, &ret, 0) < 0)
> +	test_ret = -1;
> +	if (waitpid(pid, &test_ret, 0) < 0)
>  		fprintf(stderr, "waitpid() failed: %m\n");
> -	else if (ret)
> -		fprintf(stderr, "The test returned non-zero code %d\n", ret);
> +	else if (test_ret)
> +		fprintf(stderr, "The test returned non-zero code %d\n", test_ret);
>  
>  	if (reap && sigaction(SIGCHLD, &sa, NULL)) {
>  		fprintf(stderr, "Can't set SIGCHLD handler: %m\n");
> @@ -298,15 +306,6 @@ int ns_init(int argc, char **argv)
>  			fprintf(stderr, "%d return %d\n", pid, status);
>  	}
>  
> -	/* Daemonize */
> -	write(status_pipe, &ret, sizeof(ret));
> -	close(status_pipe);
> -	if (ret)
> -		exit(ret);




> -
> -	/* suspend/resume */
> -	test_waitsig();
> -
>  	fd = open(pidfile, O_RDONLY);
>  	if (fd == -1) {
>  		fprintf(stderr, "open(%s) failed: %m\n", pidfile);
> @@ -314,12 +313,23 @@ int ns_init(int argc, char **argv)
>  	}
>  	ret = read(fd, buf, sizeof(buf) - 1);
>  	buf[ret] = '\0';
> +	close(fd);

This syscall will change errno which is printed in the next error message

>  	if (ret == -1) {
>  		fprintf(stderr, "read() failed: %m\n");
>  		exit(1);
>  	}
> -
>  	pid = atoi(buf);
> +
> +	/* Daemonize */
> +	write(status_pipe, &test_ret, sizeof(test_ret));
> +	close(status_pipe);
> +	if (test_ret)
> +		exit(test_ret);
> +
> +	while (!test_waitpre())
> +		kill(pid, SIGUSR1);
> +	/* after suspend/resume */
> +
>  	fprintf(stderr, "kill(%d, SIGTERM)\n", pid);
>  	if (pid > 0)
>  		kill(pid, SIGTERM);
> diff --git a/test/zdtm/lib/ns.h b/test/zdtm/lib/ns.h
> index 23378bc60..78395984e 100644
> --- a/test/zdtm/lib/ns.h
> +++ b/test/zdtm/lib/ns.h
> @@ -12,4 +12,10 @@ extern int ns_init(int argc, char **argv);
>  extern void test_waitsig(void);
>  extern void parseargs(int, char **);
>  
> +enum {
> +	TEST_NO_SIG = 0,
> +	TEST_SIG_PRE,
> +	TEST_SIG_STOP,
> +};
> +
>  #endif
> diff --git a/test/zdtm/lib/test.c b/test/zdtm/lib/test.c
> index 6dce027f0..c16442196 100644
> --- a/test/zdtm/lib/test.c
> +++ b/test/zdtm/lib/test.c
> @@ -35,9 +35,13 @@ static int parent;
>  
>  static void sig_hand(int signo)
>  {
> -	if (parent)
> -		futex_set_and_wake(&test_shared_state->stage, TEST_FAIL_STAGE);
> -	futex_set_and_wake(&sig_received, signo);
> +	if (signo == SIGUSR1) {
> +		futex_cmpxchg_and_wake(&sig_received, TEST_NO_SIG, TEST_SIG_PRE);
> +	} else {
> +		if (parent)
> +			futex_set_and_wake(&test_shared_state->stage, TEST_FAIL_STAGE);
> +		futex_set_and_wake(&sig_received, TEST_SIG_STOP);
> +	}
>  }
>  
>  static char *outfile;
> @@ -219,6 +223,11 @@ void test_init(int argc, char **argv)
>  		exit(1);
>  	}
>  
> +	if (sigaction(SIGUSR1, &sa, NULL)) {
> +		fprintf(stderr, "Can't set SIGUSR1 handler: %m\n");
> +		exit(1);
> +	}
> +
>  	setup_outfile();
>  	redir_stdfds();
>  
> @@ -289,12 +298,23 @@ void test_daemon()
>  
>  int test_go(void)
>  {
> -	return !futex_get(&sig_received);
> +	return futex_get(&sig_received) != TEST_SIG_STOP;
>  }
>  
>  void test_waitsig(void)
>  {
> -	futex_wait_while(&sig_received, 0);
> +	futex_wait_until(&sig_received, TEST_SIG_STOP);
> +}
> +
> +int test_waitpre(void)
> +{
> +	int ret;
> +
> +	futex_wait_while(&sig_received, TEST_NO_SIG);
> +	ret = futex_cmpxchg_and_wake(&sig_received, TEST_SIG_PRE, TEST_NO_SIG);
> +	if (ret == TEST_SIG_PRE)
> +		return 0;
> +	return 1;
>  }
>  
>  pid_t sys_clone_unified(unsigned long flags, void *child_stack, void *parent_tid,
> diff --git a/test/zdtm/lib/zdtmtst.h b/test/zdtm/lib/zdtmtst.h
> index dbe825cbc..f7af6dc1b 100644
> --- a/test/zdtm/lib/zdtmtst.h
> +++ b/test/zdtm/lib/zdtmtst.h
> @@ -41,6 +41,7 @@ extern void test_msg(const char *format, ...)
>  extern int test_go(void);
>  /* sleep until SIGTERM is delivered */
>  extern void test_waitsig(void);
> +extern int test_waitpre(void);
>  
>  #include <stdint.h>
>  
> -- 
> 2.14.3
>