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

Andrew Vagin avagin at virtuozzo.com
Thu Mar 1 03:43:33 MSK 2018


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 at 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
> 


More information about the CRIU mailing list