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