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