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