Module Name:    src
Committed By:   ozaki-r
Date:           Thu May 28 10:19:17 UTC 2015

Modified Files:
        src/tests/net/mcast: mcast.c

Log Message:
Make the test stable under load or when running on a slow machine

Let sender and receiver synchronize explicitly via a socketpair
and don't rely on sleep.


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/tests/net/mcast/mcast.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/tests/net/mcast/mcast.c
diff -u src/tests/net/mcast/mcast.c:1.2 src/tests/net/mcast/mcast.c:1.3
--- src/tests/net/mcast/mcast.c:1.2	Thu May 28 08:32:53 2015
+++ src/tests/net/mcast/mcast.c	Thu May 28 10:19:17 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: mcast.c,v 1.2 2015/05/28 08:32:53 ozaki-r Exp $	*/
+/*	$NetBSD: mcast.c,v 1.3 2015/05/28 10:19:17 ozaki-r Exp $	*/
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 #include <sys/cdefs.h>
 #ifdef __RCSID
-__RCSID("$NetBSD: mcast.c,v 1.2 2015/05/28 08:32:53 ozaki-r Exp $");
+__RCSID("$NetBSD: mcast.c,v 1.3 2015/05/28 10:19:17 ozaki-r Exp $");
 #else
 extern const char *__progname;
 #define getprogname() __progname
@@ -59,6 +59,7 @@ extern const char *__progname;
 #include <atf-c.h>
 
 #define ERRX(ev, msg, ...)	ATF_REQUIRE_MSG(0, msg, __VA_ARGS__)
+#define ERRX0(ev, msg)		ATF_REQUIRE_MSG(0, msg)
 
 #define SKIPX(ev, msg, ...)	do {			\
 	atf_tc_skip(msg, __VA_ARGS__);			\
@@ -67,6 +68,7 @@ extern const char *__progname;
 
 #else
 #define ERRX(ev, msg, ...)	errx(ev, msg, __VA_ARGS__)
+#define ERRX0(ev, msg)		errx(ev, msg)
 #define SKIPX(ev, msg, ...)	errx(ev, msg, __VA_ARGS__)
 #endif
 
@@ -232,8 +234,38 @@ out:
 	return s;
 }
 
-static void
-sender(const char *host, const char *port, size_t n, bool conn, bool bug)
+static int
+synchronize(const int fd, bool waiter)
+{
+	int syncmsg = 0;
+	int r;
+	struct pollfd pfd;
+
+	if (waiter) {
+		pfd.fd = fd;
+		pfd.events = POLLIN;
+
+		/* We use poll to avoid lock up when the peer died unexpectedly */
+		r = poll(&pfd, 1, 10000);
+		if (r == -1)
+			ERRX(EXIT_FAILURE, "poll (%s)", strerror(errno));
+		if (r == 0)
+			/* Timed out */
+			return -1;
+
+		if (read(fd, &syncmsg, sizeof(syncmsg)) == -1)
+			ERRX(EXIT_FAILURE, "read (%s)", strerror(errno));
+	} else {
+		if (write(fd, &syncmsg, sizeof(syncmsg)) == -1)
+			ERRX(EXIT_FAILURE, "write (%s)", strerror(errno));
+	}
+
+	return 0;
+}
+
+static int
+sender(const int fd, const char *host, const char *port, size_t n, bool conn,
+    bool bug)
 {
 	int s;
 	ssize_t l;
@@ -242,6 +274,11 @@ sender(const char *host, const char *por
 	socklen_t slen;
 
 	s = getsocket(host, port, conn ? connect : connector, &slen, bug);
+
+	/* Wait until receiver gets ready. */
+	if (synchronize(fd, true) == -1)
+		return -1;
+
 	for (msg.seq = 0; msg.seq < n; msg.seq++) {
 #ifdef CLOCK_MONOTONIC
 		if (clock_gettime(CLOCK_MONOTONIC, &msg.ts) == -1)
@@ -261,10 +298,17 @@ sender(const char *host, const char *por
 			ERRX(EXIT_FAILURE, "send (%s)", strerror(errno));
 		usleep(100);
 	}
+
+	/* Wait until receiver finishes its work. */
+	if (synchronize(fd, true) == -1)
+		return -1;
+
+	return 0;
 }
 
 static void
-receiver(const char *host, const char *port, size_t n, bool conn, bool bug)
+receiver(const int fd, const char *host, const char *port, size_t n, bool conn,
+    bool bug)
 {
 	int s;
 	ssize_t l;
@@ -276,6 +320,10 @@ receiver(const char *host, const char *p
 	s = getsocket(host, port, bind, &slen, bug);
 	pfd.fd = s;
 	pfd.events = POLLIN;
+
+	/* Tell I'm ready */
+	synchronize(fd, false);
+
 	for (seq = 0; seq < n; seq++) {
 		if (poll(&pfd, 1, 10000) == -1)
 			ERRX(EXIT_FAILURE, "poll (%s)", strerror(errno));
@@ -289,6 +337,9 @@ receiver(const char *host, const char *p
 			ERRX(EXIT_FAILURE, "seq: expect=%zu actual=%zu",
 			    seq, msg.seq);
 	}
+
+	/* Tell I'm finished */
+	synchronize(fd, false);
 }
 
 static void
@@ -296,22 +347,32 @@ run(const char *host, const char *port, 
 {
 	pid_t pid;
 	int status;
+	int syncfds[2];
+	int error;
+
+	if (socketpair(AF_UNIX, SOCK_STREAM, 0, syncfds) == -1)
+		ERRX(EXIT_FAILURE, "socketpair (%s)", strerror(errno));
 
 	switch ((pid = fork())) {
 	case 0:
-		receiver(host, port, n, conn, bug);
+		receiver(syncfds[0], host, port, n, conn, bug);
 		return;
 	case -1:
 		ERRX(EXIT_FAILURE, "fork (%s)", strerror(errno));
 	default:
-		usleep(1000);
-		sender(host, port, n, conn, bug);
-		usleep(100);
+		error = sender(syncfds[1], host, port, n, conn, bug);
 	again:
 		switch (waitpid(pid, &status, WNOHANG)) {
 		case -1:
 			ERRX(EXIT_FAILURE, "wait (%s)", strerror(errno));
 		case 0:
+			if (error == 0)
+				/*
+				 * Receiver is still alive, but we know
+				 * it will exit soon.
+				 */
+				goto again;
+
 			if (kill(pid, SIGTERM) == -1)
 				ERRX(EXIT_FAILURE, "kill (%s)",
 				    strerror(errno));
@@ -319,9 +380,9 @@ run(const char *host, const char *port, 
 		default:
 			if (WIFSIGNALED(status)) {
 				if (WTERMSIG(status) == SIGTERM)
-					ERRX(EXIT_FAILURE,
-					    "receiver got terminated due to " \
-					    "deadline (%d usec)", 100);
+					ERRX0(EXIT_FAILURE,
+					    "receiver failed and was killed" \
+					    "by sender");
 				else
 					ERRX(EXIT_FAILURE,
 					    "receiver got signaled (%s)",

Reply via email to