summaryrefslogtreecommitdiffstats
path: root/contrib/netbsd-tests/fs/fifofs/t_fifo.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/netbsd-tests/fs/fifofs/t_fifo.c')
-rw-r--r--contrib/netbsd-tests/fs/fifofs/t_fifo.c237
1 files changed, 237 insertions, 0 deletions
diff --git a/contrib/netbsd-tests/fs/fifofs/t_fifo.c b/contrib/netbsd-tests/fs/fifofs/t_fifo.c
new file mode 100644
index 0000000..c4a2060
--- /dev/null
+++ b/contrib/netbsd-tests/fs/fifofs/t_fifo.c
@@ -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
OpenPOWER on IntegriCloud