[CRIU] [PATCH] zdtm: fix race in test_waitsig for multithreaded tests

Andrey Vagin avagin at openvz.org
Tue Mar 5 09:15:42 EST 2013


A signal can be handled by non-leader thread and sigsuspend
will not be woken up.

kill can send signals to a specified thread, so a futex is used for
synchronization.

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 test/zdtm/lib/Makefile |  1 +
 test/zdtm/lib/lock.h   |  1 +
 test/zdtm/lib/ns.c     |  6 +++---
 test/zdtm/lib/ns.h     |  4 +++-
 test/zdtm/lib/test.c   | 24 +++++++-----------------
 5 files changed, 15 insertions(+), 21 deletions(-)

diff --git a/test/zdtm/lib/Makefile b/test/zdtm/lib/Makefile
index c90fcc4..49ef72b 100644
--- a/test/zdtm/lib/Makefile
+++ b/test/zdtm/lib/Makefile
@@ -2,6 +2,7 @@ include ../Makefile.inc
 
 CFLAGS	= -g -O2 -Wall -Werror -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0
 
+LIBDIR	= .
 LIB	= libzdtmtst.a
 
 LIBSRC	= datagen.c msg.c parseargs.c test.c streamutil.c lock.c ns.c tcp.c
diff --git a/test/zdtm/lib/lock.h b/test/zdtm/lib/lock.h
index 9abd01a..00d6458 100644
--- a/test/zdtm/lib/lock.h
+++ b/test/zdtm/lib/lock.h
@@ -1,6 +1,7 @@
 #ifndef CR_LOCK_H_
 #define CR_LOCK_H_
 
+#include <stdint.h>
 #include <linux/futex.h>
 #include <linux/unistd.h>
 #include <sys/time.h>
diff --git a/test/zdtm/lib/ns.c b/test/zdtm/lib/ns.c
index a90b0a0..4b68bde 100644
--- a/test/zdtm/lib/ns.c
+++ b/test/zdtm/lib/ns.c
@@ -103,7 +103,7 @@ static void ns_sig_hand(int signo)
 	char buf[128] = "";
 
 	if (signo == SIGTERM) {
-		sig_received = signo;
+		futex_set_and_wake(&sig_received, signo);
 		len = snprintf(buf, sizeof(buf), "Time to stop and check\n");
 		goto write_out;
 	}
@@ -114,9 +114,9 @@ static void ns_sig_hand(int signo)
 			return;
 		if (pid == -1) {
 			if (errno == ECHILD) {
-				if (sig_received)
+				if (futex_get(&sig_received))
 					return;
-				sig_received = signo;
+				futex_set_and_wake(&sig_received, signo);
 				len = snprintf(buf, sizeof(buf),
 						"All test processes exited\n");
 			} else {
diff --git a/test/zdtm/lib/ns.h b/test/zdtm/lib/ns.h
index c79cb47..23378bc 100644
--- a/test/zdtm/lib/ns.h
+++ b/test/zdtm/lib/ns.h
@@ -1,7 +1,9 @@
 #ifndef __ZDTM_NS__
 #define __ZDTM_NS__
 
-extern volatile sig_atomic_t sig_received;
+#include "lock.h"
+
+extern futex_t sig_received;
 extern char *pidfile;
 
 extern void ns_create(int argc, char **argv);
diff --git a/test/zdtm/lib/test.c b/test/zdtm/lib/test.c
index 6ba6364..f0d6483 100644
--- a/test/zdtm/lib/test.c
+++ b/test/zdtm/lib/test.c
@@ -15,13 +15,14 @@
 #include <string.h>
 
 #include "zdtmtst.h"
+#include "lock.h"
 #include "ns.h"
 
-volatile sig_atomic_t sig_received = 0;
+futex_t sig_received;
 
 static void sig_hand(int signo)
 {
-	sig_received = signo;
+	futex_set_and_wake(&sig_received, signo);
 }
 
 static char *outfile;
@@ -153,7 +154,7 @@ void test_init(int argc, char **argv)
 	if (pid) {	/* parent will exit when the child is ready */
 		test_waitsig();
 
-		if (sig_received == SIGCHLD) {
+		if (futex_get(&sig_received) == SIGCHLD) {
 			int ret;
 			waitpid(pid, &ret, 0);
 
@@ -290,7 +291,7 @@ void test_init_ns(int argc, char **argv, unsigned long clone_flags,
 	/* parent will exit when the child is ready */
 	test_waitsig();
 
-	if (sig_received == SIGCHLD) {
+	if (futex_get(&sig_received) == SIGCHLD) {
 		int ret;
 		waitpid(pid, &ret, 0);
 
@@ -330,21 +331,10 @@ out:
 
 int test_go(void)
 {
-	return !sig_received;
+	return !futex_get(&sig_received);
 }
 
 void test_waitsig(void)
 {
-	sigset_t mask, oldmask;
-
-	/* Set up the mask of signals to temporarily block. */
-	sigemptyset(&mask);
-	sigaddset(&mask, SIGTERM);
-	sigaddset(&mask, SIGCHLD);
-
-	/* Wait for a signal to arrive. */
-	sigprocmask(SIG_BLOCK, &mask, &oldmask);
-	while (!sig_received)
-		sigsuspend (&oldmask);
-	sigprocmask (SIG_UNBLOCK, &mask, NULL);
+	futex_wait_while(&sig_received, 0);
 }
-- 
1.7.11.7



More information about the CRIU mailing list