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