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