1 /* $OpenBSD: select.c,v 1.4 2018/04/26 15:55:14 guenther Exp $ */
2 /*
3 * Copyright (c) 1993, 1994, 1995, 1996 by Chris Provenzano and contributors,
4 * proven@mit.edu All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Chris Provenzano,
17 * the University of California, Berkeley, and contributors.
18 * 4. Neither the name of Chris Provenzano, the University, nor the names of
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL CHRIS PROVENZANO, THE REGENTS OR
26 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 /*
36 * Rudimentary test of select().
37 */
38
39 #include <sys/types.h>
40 #include <sys/time.h>
41 #include <errno.h>
42 #include <fcntl.h>
43 #include <pthread.h>
44 #include <pthread_np.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <unistd.h>
48 #include "test.h"
49
50 #define NLOOPS 10000
51
52 int ntouts = 0;
53
54 static void *
bg_routine(void * arg)55 bg_routine(void *arg)
56 {
57 char dot = '.';
58 int n;
59
60 SET_NAME("bg");
61
62 /* Busy loop, printing dots */
63 for (;;) {
64 pthread_yield();
65 write(STDOUT_FILENO, &dot, sizeof dot);
66 pthread_yield();
67 n = NLOOPS;
68 while (n-- > 0)
69 pthread_yield();
70 }
71 }
72
73 static void *
fg_routine(void * arg)74 fg_routine(void *arg)
75 {
76 int flags;
77 int n;
78 fd_set r;
79 int fd = fileno((FILE *) arg);
80 int tty = isatty(fd);
81 int maxfd;
82 int nb;
83 char buf[128];
84
85 SET_NAME("fg");
86
87 /* Set the file descriptor to non-blocking */
88 flags = fcntl(fd, F_GETFL);
89 CHECKr(fcntl(fd, F_SETFL, flags | O_NONBLOCK));
90
91 for (;;) {
92
93 /* Print a prompt if it's a tty: */
94 if (tty) {
95 printf("type something> ");
96 fflush(stdout);
97 }
98
99 /* Select on the fdesc: */
100 FD_ZERO(&r);
101 FD_SET(fd, &r);
102 maxfd = fd;
103 errno = 0;
104 CHECKe(n = select(maxfd + 1, &r, (fd_set *) 0, (fd_set *) 0,
105 (struct timeval *) 0));
106
107 if (n > 0) {
108 /* Something was ready for read. */
109 printf("select returned %d\n", n);
110 while ((nb = read(fd, buf, sizeof(buf) - 1)) > 0) {
111 printf("read %d: `%.*s'\n", nb, nb, buf);
112 }
113 printf("last read was %d, errno = %d %s\n", nb, errno,
114 errno == 0 ? "success" : strerror(errno));
115 if (nb < 0)
116 ASSERTe(errno, == EWOULDBLOCK ||
117 errno == EAGAIN);
118 if (nb == 0)
119 break;
120 } else
121 ntouts++;
122 }
123 printf("read finished\n");
124 return (NULL);
125 }
126
127 int
main(int argc,char * argv[])128 main(int argc, char *argv[])
129 {
130 pthread_t bg_thread, fg_thread;
131 FILE * slpr;
132
133 /* Create a fdesc that will block for a while on read: */
134 CHECKn(slpr = popen("sleep 2; echo foo", "r"));
135
136 /* Create a busy loop thread that yields a lot: */
137 CHECKr(pthread_create(&bg_thread, NULL, bg_routine, 0));
138
139 /* Create the thread that reads the fdesc: */
140 CHECKr(pthread_create(&fg_thread, NULL, fg_routine, (void *) slpr));
141
142 /* Wait for the reader thread to finish */
143 CHECKr(pthread_join(fg_thread, NULL));
144
145 /* Clean up*/
146 CHECKe(pclose(slpr));
147
148 SUCCEED;
149 }
150