[CRIU] [PATCH v2] zdtm: test -- Add trivial poll() timeout test

Andrew Vagin avagin at parallels.com
Wed Mar 18 03:49:43 PDT 2015


On Wed, Mar 18, 2015 at 10:32:55AM +0300, Cyrill Gorcunov wrote:
> Andrew, take a look please on the patch attached

> From 7742de3b34912fb7db309d44a87c6faff6be3aba Mon Sep 17 00:00:00 2001
> From: Cyrill Gorcunov <gorcunov at openvz.org>
> Date: Fri, 13 Mar 2015 19:43:07 +0300
> Subject: [PATCH v2] zdtm: test -- Add trivial poll() timeout test
> 
> The idea is simply make sure that timeour has not been
> screwed during c/r cycle.
> 
> v2:
> 
>  - Drop unneeded early poll() call.
>  - Make poll loop in cycle until caller passes c/r cycle.
>  - We should not be receiving EINTR
> 
> Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
> ---
>  test/zdtm.sh                   |   1 +
>  test/zdtm/live/static/Makefile |   1 +
>  test/zdtm/live/static/poll.c   | 150 +++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 152 insertions(+)
>  create mode 100644 test/zdtm/live/static/poll.c
> 
> diff --git a/test/zdtm.sh b/test/zdtm.sh
> index 878bfaefcef0..e879bfdd65c9 100755
> --- a/test/zdtm.sh
> +++ b/test/zdtm.sh
> @@ -151,6 +151,7 @@ generate_test_list()
>  		static/dumpable01
>  		static/dumpable02
>  		static/deleted_dev
> +		static/poll
>  	"
>  
>  	#
> diff --git a/test/zdtm/live/static/Makefile b/test/zdtm/live/static/Makefile
> index 418e138b3f14..824da1b49088 100644
> --- a/test/zdtm/live/static/Makefile
> +++ b/test/zdtm/live/static/Makefile
> @@ -92,6 +92,7 @@ TST_NOFILE	=				\
>  		tty00				\
>  		tty02				\
>  		tty03				\
> +		poll				\
>  		mountpoints			\
>  		netns				\
>  		session01			\
> diff --git a/test/zdtm/live/static/poll.c b/test/zdtm/live/static/poll.c
> new file mode 100644
> index 000000000000..67f5f6ec5f2e
> --- /dev/null
> +++ b/test/zdtm/live/static/poll.c
> @@ -0,0 +1,150 @@
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <signal.h>
> +#include <unistd.h>
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <string.h>
> +#include <utime.h>
> +#include <time.h>
> +
> +#include <sys/stat.h>
> +#include <sys/poll.h>
> +#include <sys/time.h>
> +#include <sys/types.h>
> +#include <sys/wait.h>
> +#include <sys/mman.h>
> +
> +#include "zdtmtst.h"
> +#include "lock.h"
> +
> +const char *test_doc	= "Check poll() timeouts";
> +const char *test_author	= "Cyrill Gorcunov <gorcunov at parallels.com>";
> +
> +static void show_timestamp(char *prefix, unsigned long tv_sec, unsigned long tv_usec)
> +{
> +	test_msg("%8s: sec %20lu nsec %20lu\n", prefix, tv_sec, tv_usec);
> +}
> +
> +static void show_pollfd(struct pollfd *fds, size_t nfds)
> +{
> +	size_t i;
> +
> +	for (i = 0; i < nfds; i++) {
> +		test_msg("%2zu) fd: %2d events %2x revents %2x\n",
> +			 i, fds[i].fd, fds[i].events, fds[i].revents);
> +	}
> +}
> +
> +int main(int argc, char *argv[])
> +{
> +	struct timeval time1, time2;
> +	struct timespec delay;
> +	struct pollfd ufds[2];
> +	int pipes[2], ret;
> +	int delta, status;
> +	task_waiter_t t;
> +	futex_t *f;
> +	pid_t pid;
> +
> +	test_init(argc, argv);
> +
> +	f = mmap(NULL, sizeof(*f), PROT_READ | PROT_WRITE,
> +		     MAP_ANONYMOUS | MAP_SHARED, -1, 0);
> +	if ((void *)f == MAP_FAILED) {
> +		err("Can't alloc futex");
> +		exit(1);
> +	}
> +
> +	task_waiter_init(&t);
> +	futex_init(f);
> +	futex_set(f, 1);
> +
> +	if (pipe(pipes)) {
> +		err("Can't create pipes");
> +		exit(1);
> +	}
> +
> +	memset(ufds, 0, sizeof(ufds));
> +	ufds[0].fd = pipes[0];
> +	ufds[0].events = POLLIN;
> +
> +	ufds[1].fd = pipes[1];
> +	ufds[1].events = POLLIN;
> +
> +	show_pollfd(ufds, 2);
> +
> +	if (gettimeofday(&time1, NULL)) {
> +		err("Can't get first delta");
> +		exit(1);
> +	}
> +	show_timestamp("Init", time1.tv_sec, time1.tv_usec);
> +
> +	pid = test_fork();
> +	if (pid < 0) {
> +		err("Fork failed");
> +		exit(1);
> +	} else if (pid == 0) {
> +		if (gettimeofday(&time1, NULL)) {
> +			err("Can't get from times");
> +			exit(1);
> +		}
> +
> +		show_timestamp("Start", time1.tv_sec, time1.tv_usec);
> +
> +		task_waiter_complete(&t, 1);
> +		delta = 5;
> +		while (futex_get(f) != 1) {

We can use test_go() here

> +			ret = poll(ufds, 2, delta * 1000);
> +			show_pollfd(ufds, 2);
> +			if (ret) {
> +				err("Poll-2 returned %d (events?!)", ret);
> +				exit(1);
> +			}
> +		}
> +
> +		task_waiter_wait4(&t, 2);

Why do we need this synchronization?

> +
> +		if (gettimeofday(&time2, NULL)) {
> +			err("Can't get from times");
> +			exit(1);
> +		}
> +
> +		show_timestamp("Stop", time2.tv_sec, time2.tv_usec);
> +		show_timestamp("Diff", time2.tv_sec - time1.tv_sec,
> +			       time2.tv_usec - time1.tv_usec);
> +		if ((time2.tv_sec - time1.tv_sec) > delta) {

We can call poll a few time in a loop and the test should not fail in
this case.

> +			fail("Delta is too big %lu",
> +			     (unsigned long)(time2.tv_sec - time1.tv_sec));
> +			exit(1);
> +		}
> +		exit(0);
> +	}
> +
> +	task_waiter_wait4(&t, 1);
> +
> +	/* Wait to make sure we're in poll internals */
> +	delay.tv_sec = 1;
> +	delay.tv_nsec = 0;
> +	nanosleep(&delay, NULL);
> +
> +	test_daemon();
> +	test_waitsig();
> +
> +	futex_set(f, 1);

kill(pid, SIGTERM);
> +	task_waiter_complete(&t, 2);
> +
> +	/* Return immediately if child run or stopped(by SIGSTOP) */
> +	if (waitpid(pid, &status, 0) == -1) {
> +		err("Unable to wait child");
> +		exit(1);
> +	}
> +
> +	if (!WIFEXITED(status) || WEXITSTATUS(status)) {
> +		fail("Child exited with error");
> +		exit(1);
> +	}
> +
> +	pass();
> +	return 0;
> +}
> -- 
> 1.9.3
> 



More information about the CRIU mailing list