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