Home | History | Annotate | Line # | Download | only in fifofs
t_fifo.c revision 1.1
      1  1.1  christos /* Test case written by Bharat Joshi */
      2  1.1  christos #include <sys/cdefs.h>
      3  1.1  christos __RCSID("$NetBSD: t_fifo.c,v 1.1 2011/12/21 00:17:07 christos Exp $");
      4  1.1  christos 
      5  1.1  christos #include <sys/types.h>
      6  1.1  christos #include <sys/wait.h>
      7  1.1  christos 
      8  1.1  christos #include <stdio.h>
      9  1.1  christos #include <stdlib.h>
     10  1.1  christos #include <unistd.h>
     11  1.1  christos #include <fcntl.h>
     12  1.1  christos #include <errno.h>
     13  1.1  christos #include <string.h>
     14  1.1  christos #include <err.h>
     15  1.1  christos #include <signal.h>
     16  1.1  christos 
     17  1.1  christos #ifndef STANDALONE
     18  1.1  christos #include <atf-c.h>
     19  1.1  christos #endif
     20  1.1  christos 
     21  1.1  christos #define FIFO_FILE_PATH       "./fifo_file"
     22  1.1  christos #define NUM_MESSAGES         20
     23  1.1  christos #define MSG_SIZE             240
     24  1.1  christos #define MESSAGE              "I am fine"
     25  1.1  christos 
     26  1.1  christos static int verbose = 0;
     27  1.1  christos 
     28  1.1  christos /*
     29  1.1  christos  * child_writer
     30  1.1  christos  *
     31  1.1  christos  * Function that runs in child context and opens and write to the FIFO.
     32  1.1  christos  */
     33  1.1  christos static void
     34  1.1  christos child_writer(void)
     35  1.1  christos {
     36  1.1  christos 	ssize_t rv;
     37  1.1  christos 	int fd;
     38  1.1  christos 	size_t count;
     39  1.1  christos 	char message[MSG_SIZE] = MESSAGE;
     40  1.1  christos 	static const struct timespec ts = { 0, 10000 };
     41  1.1  christos 
     42  1.1  christos 	/* Open the fifo in write-mode */
     43  1.1  christos 	for (;;) {
     44  1.1  christos 		fd = open(FIFO_FILE_PATH, O_WRONLY, 0);
     45  1.1  christos 		if (fd == -1) {
     46  1.1  christos 			if (errno == EINTR)
     47  1.1  christos 				continue;
     48  1.1  christos 			err(1, "Child: can't open fifo in write mode");
     49  1.1  christos 		}
     50  1.1  christos 		break;
     51  1.1  christos 	}
     52  1.1  christos 
     53  1.1  christos 	for (count = 0; count < NUM_MESSAGES; count++) {
     54  1.1  christos 		rv = write(fd, message, MSG_SIZE);
     55  1.1  christos 		if (rv == -1) {
     56  1.1  christos 			warn("Child: Failed to write");
     57  1.1  christos 			break;
     58  1.1  christos 		}
     59  1.1  christos 		if (rv != MSG_SIZE)
     60  1.1  christos 			warnx("Child: wrote only %zd", rv);
     61  1.1  christos 		nanosleep(&ts, NULL);
     62  1.1  christos 	}
     63  1.1  christos 
     64  1.1  christos 	close(fd);
     65  1.1  christos 	if (verbose) {
     66  1.1  christos 		printf("Child: Closed the fifo file\n");
     67  1.1  christos 		fflush(stdout);
     68  1.1  christos 	}
     69  1.1  christos }
     70  1.1  christos 
     71  1.1  christos /*
     72  1.1  christos  * _sigchild_handler
     73  1.1  christos  *
     74  1.1  christos  * Called when a sigchild is delivered
     75  1.1  christos  */
     76  1.1  christos static void
     77  1.1  christos sigchild_handler(int signo)
     78  1.1  christos {
     79  1.1  christos 	if (verbose) {
     80  1.1  christos 		if (signo == SIGCHLD) {
     81  1.1  christos 			printf("Got sigchild\n");
     82  1.1  christos 		} else {
     83  1.1  christos 			printf("Got %d signal\n", signo);
     84  1.1  christos 		}
     85  1.1  christos 		fflush(stdout);
     86  1.1  christos 	}
     87  1.1  christos 
     88  1.1  christos }
     89  1.1  christos 
     90  1.1  christos static int
     91  1.1  christos run(void)
     92  1.1  christos {
     93  1.1  christos 	pid_t pid;
     94  1.1  christos 	ssize_t rv;
     95  1.1  christos 	int fd, status;
     96  1.1  christos 	size_t buf_size = MSG_SIZE;
     97  1.1  christos 	char buf[MSG_SIZE];
     98  1.1  christos 	struct sigaction action;
     99  1.1  christos 	static const struct timespec ts = { 0, 500000000 };
    100  1.1  christos 
    101  1.1  christos 	/* Catch sigchild Signal */
    102  1.1  christos 	memset(&action, 0, sizeof(action));
    103  1.1  christos 	action.sa_handler = sigchild_handler;
    104  1.1  christos 	sigemptyset(&action.sa_mask);
    105  1.1  christos 
    106  1.1  christos 	if (sigaction(SIGCHLD, &action, NULL) == -1)
    107  1.1  christos 		err(1, "sigaction");
    108  1.1  christos 
    109  1.1  christos 	(void)unlink(FIFO_FILE_PATH);
    110  1.1  christos 	/* First create a fifo */
    111  1.1  christos 	if (mkfifo(FIFO_FILE_PATH, S_IRUSR | S_IWUSR) == -1)
    112  1.1  christos 		err(1, "mkfifo");
    113  1.1  christos 
    114  1.1  christos 	switch ((pid = fork())) {
    115  1.1  christos 	case -1:
    116  1.1  christos 		err(1, "fork");
    117  1.1  christos 	case 0:
    118  1.1  christos 		/* Open the file in write mode so that subsequent read
    119  1.1  christos 		 * from parent side does not block the parent..
    120  1.1  christos 		 */
    121  1.1  christos 		if ((fd = open(FIFO_FILE_PATH, O_WRONLY, 0)) == -1)
    122  1.1  christos 			err(1, "failed to open fifo");
    123  1.1  christos 
    124  1.1  christos 		/* In child */
    125  1.1  christos 		child_writer();
    126  1.1  christos 		return 0;
    127  1.1  christos 
    128  1.1  christos 	default:
    129  1.1  christos 		break;
    130  1.1  christos 	}
    131  1.1  christos 
    132  1.1  christos 	if (verbose) {
    133  1.1  christos 		printf("Child pid is %d\n", pid );
    134  1.1  christos 		fflush(stdout);
    135  1.1  christos 	}
    136  1.1  christos 
    137  1.1  christos 	/* In parent */
    138  1.1  christos 	for (;;) {
    139  1.1  christos 		if ((fd = open(FIFO_FILE_PATH, O_RDONLY, 0)) == -1) {
    140  1.1  christos 			if (errno == EINTR)
    141  1.1  christos 				continue;
    142  1.1  christos 			else
    143  1.1  christos 				err(1, "Failed to open the fifo in read mode");
    144  1.1  christos 		}
    145  1.1  christos 		/* Read mode is opened */
    146  1.1  christos 		break;
    147  1.1  christos 
    148  1.1  christos 	}
    149  1.1  christos 
    150  1.1  christos 	nanosleep(&ts, NULL);
    151  1.1  christos 	if (verbose) {
    152  1.1  christos 		printf("Was sleeping...\n");
    153  1.1  christos 		fflush(stdout);
    154  1.1  christos 	}
    155  1.1  christos 
    156  1.1  christos 	for (;;) {
    157  1.1  christos 		rv = read(fd, buf, buf_size);
    158  1.1  christos 
    159  1.1  christos 		if (rv == -1) {
    160  1.1  christos 			warn("Failed to read");
    161  1.1  christos 			if (errno == EINTR) {
    162  1.1  christos 				if (verbose) {
    163  1.1  christos 					printf("Parent interrupted, "
    164  1.1  christos 					    "continuing...\n");
    165  1.1  christos 					fflush(stdout);
    166  1.1  christos 				}
    167  1.1  christos 				continue;
    168  1.1  christos 			}
    169  1.1  christos 
    170  1.1  christos 			break;
    171  1.1  christos 		}
    172  1.1  christos 
    173  1.1  christos 		if (rv == 0) {
    174  1.1  christos 			if (verbose) {
    175  1.1  christos 				printf("Writers have closed, looks like we "
    176  1.1  christos 				    "are done\n");
    177  1.1  christos 				fflush(stdout);
    178  1.1  christos 			}
    179  1.1  christos 			break;
    180  1.1  christos 		}
    181  1.1  christos 
    182  1.1  christos 		if (verbose) {
    183  1.1  christos 			printf("Received %zd bytes message '%s'\n", rv, buf);
    184  1.1  christos 			fflush(stdout);
    185  1.1  christos 		}
    186  1.1  christos 	}
    187  1.1  christos 
    188  1.1  christos 	close(fd);
    189  1.1  christos 
    190  1.1  christos 	if (verbose) {
    191  1.1  christos 		printf("We are done.. now reap the child");
    192  1.1  christos 		fflush(stdout);
    193  1.1  christos 	}
    194  1.1  christos 
    195  1.1  christos 	// Read the child...
    196  1.1  christos 	while (waitpid(pid, &status, 0) == -1)
    197  1.1  christos 		if (errno != EINTR) {
    198  1.1  christos 			warn("Failed to reap the child");
    199  1.1  christos 			return 1;
    200  1.1  christos 		}
    201  1.1  christos 
    202  1.1  christos 	if (verbose) {
    203  1.1  christos 		printf("We are done completely\n");
    204  1.1  christos 		fflush(stdout);
    205  1.1  christos 	}
    206  1.1  christos 	return 0;
    207  1.1  christos }
    208  1.1  christos 
    209  1.1  christos #ifndef STANDALONE
    210  1.1  christos ATF_TC(parent_child);
    211  1.1  christos 
    212  1.1  christos ATF_TC_HEAD(parent_child, tc)
    213  1.1  christos {
    214  1.1  christos         atf_tc_set_md_var(tc, "descr", "Checks that when a fifo is shared "
    215  1.1  christos 	    "between a reader parent and a writer child, that read will "
    216  1.1  christos 	    "return EOF, and not get stuck after the child exits");
    217  1.1  christos }
    218  1.1  christos 
    219  1.1  christos ATF_TC_BODY(parent_child, tc)
    220  1.1  christos {
    221  1.1  christos         ATF_REQUIRE(run() == 0);
    222  1.1  christos }
    223  1.1  christos 
    224  1.1  christos ATF_TP_ADD_TCS(tp)
    225  1.1  christos {
    226  1.1  christos         ATF_TP_ADD_TC(tp, parent_child);
    227  1.1  christos 
    228  1.1  christos         return atf_no_error();
    229  1.1  christos }
    230  1.1  christos #else
    231  1.1  christos int
    232  1.1  christos main(void)
    233  1.1  christos {
    234  1.1  christos 	verbose = 1;
    235  1.1  christos 	return run();
    236  1.1  christos }
    237  1.1  christos #endif
    238