Module Name:    src
Committed By:   christos
Date:           Wed Dec 21 00:17:07 UTC 2011

Modified Files:
        src/tests/fs: Makefile
Added Files:
        src/tests/fs/fifofs: Makefile t_fifo.c

Log Message:
Add a test for the latest fifofs fix.


To generate a diff of this commit:
cvs rdiff -u -r1.21 -r1.22 src/tests/fs/Makefile
cvs rdiff -u -r0 -r1.1 src/tests/fs/fifofs/Makefile \
    src/tests/fs/fifofs/t_fifo.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/fs/Makefile
diff -u src/tests/fs/Makefile:1.21 src/tests/fs/Makefile:1.22
--- src/tests/fs/Makefile:1.21	Thu Mar 10 15:02:26 2011
+++ src/tests/fs/Makefile	Tue Dec 20 19:17:06 2011
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.21 2011/03/10 20:02:26 pooka Exp $
+# $NetBSD: Makefile,v 1.22 2011/12/21 00:17:06 christos Exp $
 
 .include <bsd.own.mk>
 
@@ -6,7 +6,7 @@ TESTSDIR=	${TESTSBASE}/fs
 
 SUBDIR+= 	common .WAIT
 
-TESTS_SUBDIRS+=	ffs hfs kernfs lfs msdosfs nfs nullfs psshfs ptyfs puffs
+TESTS_SUBDIRS+=	ffs fifofs hfs kernfs lfs msdosfs nfs nullfs psshfs ptyfs puffs
 TESTS_SUBDIRS+=	tmpfs umapfs union
 TESTS_SUBDIRS+=	vfs
 

Added files:

Index: src/tests/fs/fifofs/Makefile
diff -u /dev/null src/tests/fs/fifofs/Makefile:1.1
--- /dev/null	Tue Dec 20 19:17:07 2011
+++ src/tests/fs/fifofs/Makefile	Tue Dec 20 19:17:07 2011
@@ -0,0 +1,9 @@
+#	$NetBSD: Makefile,v 1.1 2011/12/21 00:17:07 christos Exp $
+#
+
+TESTSDIR=	${TESTSBASE}/fs/fifo
+WARNS=		4
+
+TESTS_C=	t_fifo
+
+.include <bsd.test.mk>
Index: src/tests/fs/fifofs/t_fifo.c
diff -u /dev/null src/tests/fs/fifofs/t_fifo.c:1.1
--- /dev/null	Tue Dec 20 19:17:07 2011
+++ src/tests/fs/fifofs/t_fifo.c	Tue Dec 20 19:17:07 2011
@@ -0,0 +1,237 @@
+/* Test case written by Bharat Joshi */
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: t_fifo.c,v 1.1 2011/12/21 00:17:07 christos Exp $");
+
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <err.h>
+#include <signal.h>
+
+#ifndef STANDALONE
+#include <atf-c.h>
+#endif
+
+#define FIFO_FILE_PATH       "./fifo_file"
+#define NUM_MESSAGES         20
+#define MSG_SIZE             240
+#define MESSAGE              "I am fine"
+
+static int verbose = 0;
+
+/*
+ * child_writer
+ *
+ * Function that runs in child context and opens and write to the FIFO.
+ */
+static void
+child_writer(void)
+{
+	ssize_t rv;
+	int fd;
+	size_t count;
+	char message[MSG_SIZE] = MESSAGE;
+	static const struct timespec ts = { 0, 10000 };
+
+	/* Open the fifo in write-mode */
+	for (;;) {
+		fd = open(FIFO_FILE_PATH, O_WRONLY, 0);
+		if (fd == -1) {
+			if (errno == EINTR)
+				continue;
+			err(1, "Child: can't open fifo in write mode");
+		}
+		break;
+	}
+
+	for (count = 0; count < NUM_MESSAGES; count++) {
+		rv = write(fd, message, MSG_SIZE);
+		if (rv == -1) {
+			warn("Child: Failed to write");
+			break;
+		}
+		if (rv != MSG_SIZE)
+			warnx("Child: wrote only %zd", rv);
+		nanosleep(&ts, NULL);
+	}
+
+	close(fd);
+	if (verbose) {
+		printf("Child: Closed the fifo file\n");
+		fflush(stdout);
+	}
+}
+
+/*
+ * _sigchild_handler
+ *
+ * Called when a sigchild is delivered
+ */
+static void
+sigchild_handler(int signo)
+{
+	if (verbose) {
+		if (signo == SIGCHLD) {
+			printf("Got sigchild\n");
+		} else {
+			printf("Got %d signal\n", signo);
+		}
+		fflush(stdout);
+	}
+
+}
+
+static int
+run(void)
+{
+	pid_t pid;
+	ssize_t rv;
+	int fd, status;
+	size_t buf_size = MSG_SIZE;
+	char buf[MSG_SIZE];
+	struct sigaction action;
+	static const struct timespec ts = { 0, 500000000 };
+
+	/* Catch sigchild Signal */
+	memset(&action, 0, sizeof(action));
+	action.sa_handler = sigchild_handler;
+	sigemptyset(&action.sa_mask);
+
+	if (sigaction(SIGCHLD, &action, NULL) == -1)
+		err(1, "sigaction");
+
+	(void)unlink(FIFO_FILE_PATH);
+	/* First create a fifo */
+	if (mkfifo(FIFO_FILE_PATH, S_IRUSR | S_IWUSR) == -1)
+		err(1, "mkfifo");
+
+	switch ((pid = fork())) {
+	case -1:
+		err(1, "fork");
+	case 0:
+		/* Open the file in write mode so that subsequent read 
+		 * from parent side does not block the parent..
+		 */
+		if ((fd = open(FIFO_FILE_PATH, O_WRONLY, 0)) == -1)
+			err(1, "failed to open fifo");
+
+		/* In child */
+		child_writer();
+		return 0;
+
+	default:
+		break;
+	}
+
+	if (verbose) {
+		printf("Child pid is %d\n", pid );
+		fflush(stdout);
+	}
+
+	/* In parent */
+	for (;;) {
+		if ((fd = open(FIFO_FILE_PATH, O_RDONLY, 0)) == -1) {
+			if (errno == EINTR)
+				continue;
+			else
+				err(1, "Failed to open the fifo in read mode");
+		}
+		/* Read mode is opened */
+		break;
+
+	}
+
+	nanosleep(&ts, NULL);
+	if (verbose) {
+		printf("Was sleeping...\n");
+		fflush(stdout);
+	}
+
+	for (;;) {
+		rv = read(fd, buf, buf_size);
+
+		if (rv == -1) {
+			warn("Failed to read");
+			if (errno == EINTR) {
+				if (verbose) {
+					printf("Parent interrupted, "
+					    "continuing...\n");
+					fflush(stdout);
+				}
+				continue;
+			}
+
+			break;
+		}
+
+		if (rv == 0) {
+			if (verbose) {
+				printf("Writers have closed, looks like we "
+				    "are done\n");
+				fflush(stdout);
+			}
+			break;
+		}
+
+		if (verbose) {
+			printf("Received %zd bytes message '%s'\n", rv, buf);
+			fflush(stdout);
+		}
+	}
+
+	close(fd);
+
+	if (verbose) {
+		printf("We are done.. now reap the child");
+		fflush(stdout);
+	}
+
+	// Read the child...
+	while (waitpid(pid, &status, 0) == -1)
+		if (errno != EINTR) {
+			warn("Failed to reap the child");
+			return 1;
+		}
+
+	if (verbose) {
+		printf("We are done completely\n");
+		fflush(stdout);
+	}
+	return 0;
+}
+
+#ifndef STANDALONE
+ATF_TC(parent_child);      
+
+ATF_TC_HEAD(parent_child, tc)
+{
+        atf_tc_set_md_var(tc, "descr", "Checks that when a fifo is shared "
+	    "between a reader parent and a writer child, that read will "
+	    "return EOF, and not get stuck after the child exits");
+}
+ 
+ATF_TC_BODY(parent_child, tc)
+{       
+        ATF_REQUIRE(run() == 0);
+}       
+
+ATF_TP_ADD_TCS(tp)
+{       
+        ATF_TP_ADD_TC(tp, parent_child);
+        
+        return atf_no_error();
+}       
+#else
+int
+main(void)
+{
+	verbose = 1;
+	return run();
+}
+#endif

Reply via email to