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