xref: /openbsd-src/regress/lib/libpthread/poll/poll.c (revision 04e62e6e0a2e1a9ab86abf920a37067c05e53e14)
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