xref: /freebsd/contrib/netbsd-tests/fs/fifofs/t_fifo.c (revision d370fd1cd8fc69e87dc63f4f4a82e5a8b4956c93)
157718be8SEnji Cooper /* Test case written by Bharat Joshi */
257718be8SEnji Cooper #include <sys/cdefs.h>
3*cdebaff8SEnji Cooper __RCSID("$NetBSD: t_fifo.c,v 1.2 2017/01/10 22:36:29 christos Exp $");
457718be8SEnji Cooper 
557718be8SEnji Cooper #include <sys/types.h>
657718be8SEnji Cooper #include <sys/wait.h>
7*cdebaff8SEnji Cooper #include <sys/stat.h>
857718be8SEnji Cooper 
957718be8SEnji Cooper #include <stdio.h>
1057718be8SEnji Cooper #include <stdlib.h>
1157718be8SEnji Cooper #include <unistd.h>
1257718be8SEnji Cooper #include <fcntl.h>
1357718be8SEnji Cooper #include <errno.h>
1457718be8SEnji Cooper #include <string.h>
1557718be8SEnji Cooper #include <err.h>
1657718be8SEnji Cooper #include <signal.h>
1757718be8SEnji Cooper 
1857718be8SEnji Cooper #ifndef STANDALONE
1957718be8SEnji Cooper #include <atf-c.h>
2057718be8SEnji Cooper #endif
2157718be8SEnji Cooper 
2257718be8SEnji Cooper #define FIFO_FILE_PATH       "./fifo_file"
2357718be8SEnji Cooper #define NUM_MESSAGES         20
2457718be8SEnji Cooper #define MSG_SIZE             240
2557718be8SEnji Cooper #define MESSAGE              "I am fine"
2657718be8SEnji Cooper 
2757718be8SEnji Cooper static int verbose = 0;
2857718be8SEnji Cooper 
2957718be8SEnji Cooper /*
3057718be8SEnji Cooper  * child_writer
3157718be8SEnji Cooper  *
3257718be8SEnji Cooper  * Function that runs in child context and opens and write to the FIFO.
3357718be8SEnji Cooper  */
3457718be8SEnji Cooper static void
child_writer(void)3557718be8SEnji Cooper child_writer(void)
3657718be8SEnji Cooper {
3757718be8SEnji Cooper 	ssize_t rv;
3857718be8SEnji Cooper 	int fd;
3957718be8SEnji Cooper 	size_t count;
4057718be8SEnji Cooper 	char message[MSG_SIZE] = MESSAGE;
4157718be8SEnji Cooper 	static const struct timespec ts = { 0, 10000 };
4257718be8SEnji Cooper 
4357718be8SEnji Cooper 	/* Open the fifo in write-mode */
4457718be8SEnji Cooper 	for (;;) {
4557718be8SEnji Cooper 		fd = open(FIFO_FILE_PATH, O_WRONLY, 0);
4657718be8SEnji Cooper 		if (fd == -1) {
4757718be8SEnji Cooper 			if (errno == EINTR)
4857718be8SEnji Cooper 				continue;
4957718be8SEnji Cooper 			err(1, "Child: can't open fifo in write mode");
5057718be8SEnji Cooper 		}
5157718be8SEnji Cooper 		break;
5257718be8SEnji Cooper 	}
5357718be8SEnji Cooper 
5457718be8SEnji Cooper 	for (count = 0; count < NUM_MESSAGES; count++) {
5557718be8SEnji Cooper 		rv = write(fd, message, MSG_SIZE);
5657718be8SEnji Cooper 		if (rv == -1) {
5757718be8SEnji Cooper 			warn("Child: Failed to write");
5857718be8SEnji Cooper 			break;
5957718be8SEnji Cooper 		}
6057718be8SEnji Cooper 		if (rv != MSG_SIZE)
6157718be8SEnji Cooper 			warnx("Child: wrote only %zd", rv);
6257718be8SEnji Cooper 		nanosleep(&ts, NULL);
6357718be8SEnji Cooper 	}
6457718be8SEnji Cooper 
6557718be8SEnji Cooper 	close(fd);
6657718be8SEnji Cooper 	if (verbose) {
6757718be8SEnji Cooper 		printf("Child: Closed the fifo file\n");
6857718be8SEnji Cooper 		fflush(stdout);
6957718be8SEnji Cooper 	}
7057718be8SEnji Cooper }
7157718be8SEnji Cooper 
7257718be8SEnji Cooper /*
7357718be8SEnji Cooper  * _sigchild_handler
7457718be8SEnji Cooper  *
7557718be8SEnji Cooper  * Called when a sigchild is delivered
7657718be8SEnji Cooper  */
7757718be8SEnji Cooper static void
sigchild_handler(int signo)7857718be8SEnji Cooper sigchild_handler(int signo)
7957718be8SEnji Cooper {
8057718be8SEnji Cooper 	if (verbose) {
8157718be8SEnji Cooper 		if (signo == SIGCHLD) {
8257718be8SEnji Cooper 			printf("Got sigchild\n");
8357718be8SEnji Cooper 		} else {
8457718be8SEnji Cooper 			printf("Got %d signal\n", signo);
8557718be8SEnji Cooper 		}
8657718be8SEnji Cooper 		fflush(stdout);
8757718be8SEnji Cooper 	}
8857718be8SEnji Cooper 
8957718be8SEnji Cooper }
9057718be8SEnji Cooper 
9157718be8SEnji Cooper static int
run(void)9257718be8SEnji Cooper run(void)
9357718be8SEnji Cooper {
9457718be8SEnji Cooper 	pid_t pid;
9557718be8SEnji Cooper 	ssize_t rv;
9657718be8SEnji Cooper 	int fd, status;
9757718be8SEnji Cooper 	size_t buf_size = MSG_SIZE;
9857718be8SEnji Cooper 	char buf[MSG_SIZE];
9957718be8SEnji Cooper 	struct sigaction action;
10057718be8SEnji Cooper 	static const struct timespec ts = { 0, 500000000 };
10157718be8SEnji Cooper 
10257718be8SEnji Cooper 	/* Catch sigchild Signal */
10357718be8SEnji Cooper 	memset(&action, 0, sizeof(action));
10457718be8SEnji Cooper 	action.sa_handler = sigchild_handler;
10557718be8SEnji Cooper 	sigemptyset(&action.sa_mask);
10657718be8SEnji Cooper 
10757718be8SEnji Cooper 	if (sigaction(SIGCHLD, &action, NULL) == -1)
10857718be8SEnji Cooper 		err(1, "sigaction");
10957718be8SEnji Cooper 
11057718be8SEnji Cooper 	(void)unlink(FIFO_FILE_PATH);
11157718be8SEnji Cooper 	/* First create a fifo */
11257718be8SEnji Cooper 	if (mkfifo(FIFO_FILE_PATH, S_IRUSR | S_IWUSR) == -1)
11357718be8SEnji Cooper 		err(1, "mkfifo");
11457718be8SEnji Cooper 
11557718be8SEnji Cooper 	switch ((pid = fork())) {
11657718be8SEnji Cooper 	case -1:
11757718be8SEnji Cooper 		err(1, "fork");
11857718be8SEnji Cooper 	case 0:
11957718be8SEnji Cooper 		/* Open the file in write mode so that subsequent read
12057718be8SEnji Cooper 		 * from parent side does not block the parent..
12157718be8SEnji Cooper 		 */
12257718be8SEnji Cooper 		if ((fd = open(FIFO_FILE_PATH, O_WRONLY, 0)) == -1)
12357718be8SEnji Cooper 			err(1, "failed to open fifo");
12457718be8SEnji Cooper 
12557718be8SEnji Cooper 		/* In child */
12657718be8SEnji Cooper 		child_writer();
12757718be8SEnji Cooper 		return 0;
12857718be8SEnji Cooper 
12957718be8SEnji Cooper 	default:
13057718be8SEnji Cooper 		break;
13157718be8SEnji Cooper 	}
13257718be8SEnji Cooper 
13357718be8SEnji Cooper 	if (verbose) {
13457718be8SEnji Cooper 		printf("Child pid is %d\n", pid );
13557718be8SEnji Cooper 		fflush(stdout);
13657718be8SEnji Cooper 	}
13757718be8SEnji Cooper 
13857718be8SEnji Cooper 	/* In parent */
13957718be8SEnji Cooper 	for (;;) {
14057718be8SEnji Cooper 		if ((fd = open(FIFO_FILE_PATH, O_RDONLY, 0)) == -1) {
14157718be8SEnji Cooper 			if (errno == EINTR)
14257718be8SEnji Cooper 				continue;
14357718be8SEnji Cooper 			else
14457718be8SEnji Cooper 				err(1, "Failed to open the fifo in read mode");
14557718be8SEnji Cooper 		}
14657718be8SEnji Cooper 		/* Read mode is opened */
14757718be8SEnji Cooper 		break;
14857718be8SEnji Cooper 
14957718be8SEnji Cooper 	}
15057718be8SEnji Cooper 
15157718be8SEnji Cooper 	nanosleep(&ts, NULL);
15257718be8SEnji Cooper 	if (verbose) {
15357718be8SEnji Cooper 		printf("Was sleeping...\n");
15457718be8SEnji Cooper 		fflush(stdout);
15557718be8SEnji Cooper 	}
15657718be8SEnji Cooper 
15757718be8SEnji Cooper 	for (;;) {
15857718be8SEnji Cooper 		rv = read(fd, buf, buf_size);
15957718be8SEnji Cooper 
16057718be8SEnji Cooper 		if (rv == -1) {
16157718be8SEnji Cooper 			warn("Failed to read");
16257718be8SEnji Cooper 			if (errno == EINTR) {
16357718be8SEnji Cooper 				if (verbose) {
16457718be8SEnji Cooper 					printf("Parent interrupted, "
16557718be8SEnji Cooper 					    "continuing...\n");
16657718be8SEnji Cooper 					fflush(stdout);
16757718be8SEnji Cooper 				}
16857718be8SEnji Cooper 				continue;
16957718be8SEnji Cooper 			}
17057718be8SEnji Cooper 
17157718be8SEnji Cooper 			break;
17257718be8SEnji Cooper 		}
17357718be8SEnji Cooper 
17457718be8SEnji Cooper 		if (rv == 0) {
17557718be8SEnji Cooper 			if (verbose) {
17657718be8SEnji Cooper 				printf("Writers have closed, looks like we "
17757718be8SEnji Cooper 				    "are done\n");
17857718be8SEnji Cooper 				fflush(stdout);
17957718be8SEnji Cooper 			}
18057718be8SEnji Cooper 			break;
18157718be8SEnji Cooper 		}
18257718be8SEnji Cooper 
18357718be8SEnji Cooper 		if (verbose) {
18457718be8SEnji Cooper 			printf("Received %zd bytes message '%s'\n", rv, buf);
18557718be8SEnji Cooper 			fflush(stdout);
18657718be8SEnji Cooper 		}
18757718be8SEnji Cooper 	}
18857718be8SEnji Cooper 
18957718be8SEnji Cooper 	close(fd);
19057718be8SEnji Cooper 
19157718be8SEnji Cooper 	if (verbose) {
19257718be8SEnji Cooper 		printf("We are done.. now reap the child");
19357718be8SEnji Cooper 		fflush(stdout);
19457718be8SEnji Cooper 	}
19557718be8SEnji Cooper 
19657718be8SEnji Cooper 	// Read the child...
19757718be8SEnji Cooper 	while (waitpid(pid, &status, 0) == -1)
19857718be8SEnji Cooper 		if (errno != EINTR) {
19957718be8SEnji Cooper 			warn("Failed to reap the child");
20057718be8SEnji Cooper 			return 1;
20157718be8SEnji Cooper 		}
20257718be8SEnji Cooper 
20357718be8SEnji Cooper 	if (verbose) {
20457718be8SEnji Cooper 		printf("We are done completely\n");
20557718be8SEnji Cooper 		fflush(stdout);
20657718be8SEnji Cooper 	}
20757718be8SEnji Cooper 	return 0;
20857718be8SEnji Cooper }
20957718be8SEnji Cooper 
21057718be8SEnji Cooper #ifndef STANDALONE
21157718be8SEnji Cooper ATF_TC(parent_child);
21257718be8SEnji Cooper 
ATF_TC_HEAD(parent_child,tc)21357718be8SEnji Cooper ATF_TC_HEAD(parent_child, tc)
21457718be8SEnji Cooper {
21557718be8SEnji Cooper         atf_tc_set_md_var(tc, "descr", "Checks that when a fifo is shared "
21657718be8SEnji Cooper 	    "between a reader parent and a writer child, that read will "
21757718be8SEnji Cooper 	    "return EOF, and not get stuck after the child exits");
21857718be8SEnji Cooper }
21957718be8SEnji Cooper 
ATF_TC_BODY(parent_child,tc)22057718be8SEnji Cooper ATF_TC_BODY(parent_child, tc)
22157718be8SEnji Cooper {
22257718be8SEnji Cooper         ATF_REQUIRE(run() == 0);
22357718be8SEnji Cooper }
22457718be8SEnji Cooper 
ATF_TP_ADD_TCS(tp)22557718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
22657718be8SEnji Cooper {
22757718be8SEnji Cooper         ATF_TP_ADD_TC(tp, parent_child);
22857718be8SEnji Cooper 
22957718be8SEnji Cooper         return atf_no_error();
23057718be8SEnji Cooper }
23157718be8SEnji Cooper #else
23257718be8SEnji Cooper int
main(void)23357718be8SEnji Cooper main(void)
23457718be8SEnji Cooper {
23557718be8SEnji Cooper 	verbose = 1;
23657718be8SEnji Cooper 	return run();
23757718be8SEnji Cooper }
23857718be8SEnji Cooper #endif
239