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