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