[7/8] zdtm/lib: add test_waitpre so that test knows about predump iters

Submitted by Pavel Tikhomirov on Feb. 15, 2018, 10:06 a.m.

Details

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

Commit Message

Pavel Tikhomirov Feb. 15, 2018, 10:06 a.m.
From: ptikhomirov <ptikhomirov@virtuozzo.com>

- 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 767a1ed50..698092bcb 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
@@ -1184,6 +1191,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>