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
print_pollfd(struct pollfd * p)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 *
writer(void * arg)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 *
reader(void * arg)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
main(int argc,char * argv[])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