[CRIU] [PATCH 3/3] zdtm: use a unix socket instead of a pipe to synchronizer processes

Andrei Vagin avagin at openvz.org
Thu Dec 29 17:28:38 PST 2016


From: Andrei Vagin <avagin at virtuozzo.com>

A unix socket can be bound to itself, so we need only one socket
instead of a pair of pipe.

If we use a socket, we can peek a message and if it isn't for us
we don't need to send it back.

Currently a process reads message from pipe, if it isn't for him,
it sends it back and sleeps for a random timeout. In a worst case
each waiter will read and send a message back, before the right
one will get it.

Signed-off-by: Andrei Vagin <avagin at virtuozzo.com>
---
 test/zdtm/lib/lock.c    | 54 ++++++++++++++++++++++++++++++++++++++++---------
 test/zdtm/lib/zdtmtst.h |  2 +-
 2 files changed, 46 insertions(+), 10 deletions(-)

diff --git a/test/zdtm/lib/lock.c b/test/zdtm/lib/lock.c
index 9d2a646..9c3ec87 100644
--- a/test/zdtm/lib/lock.c
+++ b/test/zdtm/lib/lock.c
@@ -7,6 +7,9 @@
 #include <unistd.h>
 #include <linux/unistd.h>
 #include <time.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/stat.h>
 
 #include "zdtmtst.h"
 
@@ -19,19 +22,52 @@ static long sys_gettid(void)
 
 void task_waiter_init(task_waiter_t *t)
 {
+	struct sockaddr_un addr;
+	unsigned int addrlen;
+	struct stat st;
+	int sk;
+
 	datagen((void *)&t->seed, sizeof(t->seed), NULL);
 	t->seed = t->seed % TASK_WAITER_INITIAL;
 
-	if (pipe(t->pipes)) {
-		pr_perror("task_waiter_init failed");
-		exit(1);
+	sk = socket(AF_UNIX, SOCK_DGRAM, 0);
+	if (sk < 0) {
+		pr_perror("Unable to create a socket");
+		goto err;
+	}
+
+	if (fstat(sk, &st)) {
+		pr_perror("Unable to stat a file descriptor");
+		close(sk);
+		goto err;
 	}
+
+	addr.sun_family = AF_UNIX;
+	addrlen = snprintf(addr.sun_path, sizeof(addr.sun_path), "X/criu-zdtm-%lx", st.st_ino);
+	addrlen += sizeof(addr.sun_family);
+
+	addr.sun_path[0] = 0;
+	if (bind(sk, &addr, addrlen)) {
+		pr_perror("Unable to bind a socket");
+		close(sk);
+		goto err;
+	}
+	if (connect(sk, &addr, addrlen)) {
+		pr_perror("Unable to connect a socket");
+		close(sk);
+		goto err;
+	}
+
+	t->sk = sk;
+	return;
+err:
+	exit(1);
 }
 
 void task_waiter_fini(task_waiter_t *t)
 {
-	close(t->pipes[0]);
-	close(t->pipes[1]);
+	close(t->sk);
+	t->sk = -1;
 }
 
 void task_waiter_wait4(task_waiter_t *t, unsigned int lockid)
@@ -41,7 +77,7 @@ void task_waiter_wait4(task_waiter_t *t, unsigned int lockid)
 	unsigned int v;
 
 	for (;;) {
-		if (read(t->pipes[0], &v, sizeof(v)) != sizeof(v))
+		if (recv(t->sk, &v, sizeof(v), MSG_PEEK) != sizeof(v))
 			goto err;
 
 		/*
@@ -53,8 +89,6 @@ void task_waiter_wait4(task_waiter_t *t, unsigned int lockid)
 		 * next attempt.
 		 */
 		if (v != lockid) {
-			if (write(t->pipes[1], &v, sizeof(v)) != sizeof(v))
-				goto err;
 			/*
 			 * If we get a collision in access, lets sleep
 			 * semi-random time magnitude to decrease probability
@@ -65,6 +99,8 @@ void task_waiter_wait4(task_waiter_t *t, unsigned int lockid)
 		} else
 			break;
 	}
+	if (recv(t->sk, &v, sizeof(v), 0) != sizeof(v))
+		goto err;
 
 	return;
 
@@ -75,7 +111,7 @@ err:
 
 void task_waiter_complete(task_waiter_t *t, unsigned int lockid)
 {
-	if (write(t->pipes[1], &lockid, sizeof(lockid)) != sizeof(lockid)) {
+	if (write(t->sk, &lockid, sizeof(lockid)) != sizeof(lockid)) {
 		pr_perror("task_waiter_complete failed");
 		exit(1);
 	}
diff --git a/test/zdtm/lib/zdtmtst.h b/test/zdtm/lib/zdtmtst.h
index 3f9f550..9770f74 100644
--- a/test/zdtm/lib/zdtmtst.h
+++ b/test/zdtm/lib/zdtmtst.h
@@ -129,7 +129,7 @@ extern int zdtm_seccomp;
 
 typedef struct {
 	unsigned long	seed;
-	int		pipes[2];
+	int		sk;
 } task_waiter_t;
 
 extern void task_waiter_init(task_waiter_t *t);
-- 
2.7.4



More information about the CRIU mailing list