1 /* $OpenBSD: poll.c,v 1.3 2001/09/20 16:43:15 todd Exp $ */ 2 /* David Leonard <d@openbsd.org>, 2001. Public Domain. */ 3 4 #include <pthread.h> 5 #include <fcntl.h> 6 #include <poll.h> 7 #include <paths.h> 8 #include <unistd.h> 9 #include <stdlib.h> 10 #include "test.h" 11 12 13 #define POLLALL (POLLIN|POLLOUT|POLLERR|POLLNVAL) 14 15 static void 16 print_pollfd(p) 17 struct pollfd *p; 18 { 19 20 printf("{fd=%d, events=< %s%s%s> revents=< %s%s%s%s%s>}", 21 p->fd, 22 p->events & POLLIN ? "in " : "", 23 p->events & POLLOUT ? "out " : "", 24 p->events & ~(POLLIN|POLLOUT) ? "XXX " : "", 25 p->revents & POLLIN ? "in " : "", 26 p->revents & POLLOUT ? "out " : "", 27 p->revents & POLLERR ? "err " : "", 28 p->revents & POLLHUP ? "hup " : "", 29 p->revents & POLLNVAL ? "nval " : "" 30 ); 31 } 32 33 static void * 34 writer(arg) 35 void *arg; 36 { 37 int fd = *(int *)arg; 38 const char msg[1] = { '!' }; 39 40 ASSERTe(write(fd, &msg, sizeof msg), == sizeof msg); 41 return NULL; 42 } 43 44 static void * 45 reader(arg) 46 void *arg; 47 { 48 int fd = *(int *)arg; 49 char buf[1]; 50 51 ASSERTe(read(fd, &buf, sizeof buf), == sizeof buf); 52 return NULL; 53 } 54 55 int 56 main(argc, argv) 57 int argc; 58 char **argv; 59 { 60 pthread_t t; 61 void *result; 62 int null, zero, tty; 63 int tube[2]; 64 struct pollfd p[3]; 65 66 /* Try an empty poll set */ 67 ASSERTe(poll(NULL, 0, 0), == 0); 68 69 CHECKe(zero = open(_PATH_DEV "zero", O_RDONLY)); 70 CHECKe(null = open(_PATH_DEV "null", O_WRONLY)); 71 CHECKe(tty = open(_PATH_DEV "tty", O_WRONLY)); 72 73 /* Try both descriptors being ready */ 74 p[0].fd = zero; 75 p[0].events = POLLIN|POLLOUT; 76 p[0].revents = 0; 77 p[1].fd = null; 78 p[1].events = POLLIN|POLLOUT; 79 p[1].revents = 0; 80 81 ASSERTe(poll(p, 2, 0), == 2); /* if 4 then bug in kernel not fixed */ 82 printf("zero p[0]="); print_pollfd(&p[0]); putchar('\n'); 83 printf("null p[1]="); print_pollfd(&p[1]); putchar('\n'); 84 ASSERT((p[0].revents & POLLIN) == POLLIN); 85 ASSERT((p[1].revents & POLLOUT) == POLLOUT); 86 87 /* 88 * Try one of the descriptors being invalid 89 * and the other ready 90 */ 91 printf("closing zero\n"); 92 close(zero); 93 94 p[0].fd = zero; 95 p[0].events = POLLIN|POLLOUT; 96 p[1].fd = null; 97 p[1].events = POLLIN|POLLOUT; 98 ASSERTe(poll(p, 2, 0), == 2); /* again, old kernels had this bug */ 99 printf("zero p[0]="); print_pollfd(&p[0]); putchar('\n'); 100 printf("null p[1]="); print_pollfd(&p[1]); putchar('\n'); 101 ASSERT((p[0].revents & POLLNVAL) == POLLNVAL); 102 ASSERT((p[1].revents & POLLOUT) == POLLOUT); 103 104 printf("closing null\n"); 105 close(null); 106 107 /* 108 * New pipes. the write end should be writable (buffered) 109 */ 110 CHECKe(pipe(tube)); 111 CHECKe(fcntl(tube[0], F_SETFL, O_NONBLOCK)); 112 CHECKe(fcntl(tube[1], F_SETFL, O_NONBLOCK)); 113 114 p[0].fd = tube[0]; 115 p[0].events = POLLIN; 116 p[1].fd = tube[1]; 117 p[1].events = POLLOUT; 118 ASSERTe(poll(p, 2, 0), == 1); 119 printf("rpipe p[0]="); print_pollfd(&p[0]); putchar('\n'); 120 printf("wpipe p[1]="); print_pollfd(&p[1]); putchar('\n'); 121 ASSERT(p[0].revents == 0); 122 ASSERT(p[1].revents == POLLOUT); 123 124 /* Start a writing thread to the write end [1] */ 125 printf("bg writing to wpipe\n"); 126 CHECKr(pthread_create(&t, NULL, writer, (void *)&tube[1])); 127 /* The read end [0] should soon be ready for read (POLLIN) */ 128 p[0].fd = tube[0]; 129 p[0].events = POLLIN; 130 ASSERTe(poll(p, 1, INFTIM), == 1); 131 printf("rpipe p[0]="); print_pollfd(&p[0]); putchar('\n'); 132 ASSERT(p[0].revents == POLLIN); 133 reader((void *)&tube[0]); /* consume */ 134 CHECKr(pthread_join(t, &result)); 135 136 SUCCEED; 137 } 138