[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