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