]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/select.cc
Throughout, update copyrights to reflect dates which correspond to main-branch
[newlib-cygwin.git] / winsup / cygwin / select.cc
CommitLineData
1fd5e000
CF
1/* select.cc
2
bc837d22
CF
3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
4 2007, 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc.
1fd5e000 5
1fd5e000
CF
6This file is part of Cygwin.
7
8This software is a copyrighted work licensed under the terms of the
9Cygwin license. Please consult the file "CYGWIN_LICENSE" for
10details. */
11
1cda1322
CF
12/* The following line means that the BSD socket definitions for
13 fd_set, FD_ISSET etc. are used in this file. */
1fd5e000
CF
14
15#define __INSIDE_CYGWIN_NET__
1fd5e000 16
4c8d72de 17#include "winsup.h"
1fd5e000 18#include <stdlib.h>
023c2582 19#include <sys/param.h>
11a36faa 20#include "ntdll.h"
1fd5e000 21
4c8d72de
DD
22#include <wingdi.h>
23#include <winuser.h>
a1299ba5 24#define USE_SYS_TYPES_FD_SET
c487f2fe 25#include <winsock2.h>
db80f635 26#include <netdb.h>
9e2baf8d 27#include "cygerrno.h"
6b91b8d5 28#include "security.h"
47063f00 29#include "path.h"
7ac61736 30#include "fhandler.h"
b4fa8164 31#include "select.h"
bccd5e0d 32#include "dtable.h"
0381fec6 33#include "cygheap.h"
d02099f2 34#include "pinfo.h"
bccd5e0d 35#include "sigproc.h"
1cda1322 36#include "cygtls.h"
4ae63783 37#include "cygwait.h"
1fd5e000
CF
38
39/*
40 * All these defines below should be in sys/types.h
41 * but because of the includes above, they may not have
42 * been included. We create special UNIX_xxxx versions here.
43 */
44
45#ifndef NBBY
46#define NBBY 8 /* number of bits in a byte */
47#endif /* NBBY */
48
49/*
50 * Select uses bit masks of file descriptors in longs.
51 * These macros manipulate such bit fields (the filesystem macros use chars).
52 * FD_SETSIZE may be defined by the user, but the default here
53 * should be >= NOFILE (param.h).
54 */
55
56typedef long fd_mask;
57#define UNIX_NFDBITS (sizeof (fd_mask) * NBBY) /* bits per mask */
58#ifndef unix_howmany
59#define unix_howmany(x,y) (((x)+((y)-1))/(y))
60#endif
61
62#define unix_fd_set fd_set
63
a1299ba5 64#define NULL_fd_set ((fd_set *) NULL)
1fd5e000 65#define sizeof_fd_set(n) \
c90e1cf1 66 ((unsigned) (NULL_fd_set->fds_bits + unix_howmany ((n), UNIX_NFDBITS)))
1fd5e000
CF
67#define UNIX_FD_SET(n, p) \
68 ((p)->fds_bits[(n)/UNIX_NFDBITS] |= (1L << ((n) % UNIX_NFDBITS)))
69#define UNIX_FD_CLR(n, p) \
70 ((p)->fds_bits[(n)/UNIX_NFDBITS] &= ~(1L << ((n) % UNIX_NFDBITS)))
71#define UNIX_FD_ISSET(n, p) \
72 ((p)->fds_bits[(n)/UNIX_NFDBITS] & (1L << ((n) % UNIX_NFDBITS)))
73#define UNIX_FD_ZERO(p, n) \
b4fa8164 74 memset ((caddr_t) (p), 0, sizeof_fd_set ((n)))
1fd5e000 75
b052bf26
CF
76#define allocfd_set(n) ({\
77 size_t __sfds = sizeof_fd_set (n) + 8; \
78 void *__res = alloca (__sfds); \
79 memset (__res, 0, __sfds); \
80 (fd_set *) __res; \
81})
82
1fd5e000
CF
83#define copyfd_set(to, from, n) memcpy (to, from, sizeof_fd_set (n));
84
1fd5e000
CF
85#define set_handle_or_return_if_not_open(h, s) \
86 h = (s)->fh->get_handle (); \
0381fec6 87 if (cygheap->fdtab.not_open ((s)->fd)) \
1fd5e000 88 { \
169c465a 89 (s)->thread_errno = EBADF; \
1fd5e000 90 return -1; \
45b61a88 91 }
1fd5e000 92
b052bf26
CF
93static int select (int, fd_set *, fd_set *, fd_set *, DWORD);
94
95/* The main select code. */
c367dfd0 96extern "C" int
0072fdab
CF
97cygwin_select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
98 struct timeval *to)
1fd5e000 99{
45b61a88
CF
100 select_printf ("select(%d, %p, %p, %p, %p)", maxfds, readfds, writefds, exceptfds, to);
101
45b61a88 102 pthread_testcancel ();
962f9a2c
CF
103 int res;
104 if (maxfds < 0)
105 {
106 set_errno (EINVAL);
107 res = -1;
108 }
1fd5e000 109 else
962f9a2c
CF
110 {
111 /* Convert to milliseconds or INFINITE if to == NULL */
112 DWORD ms = to ? (to->tv_sec * 1000) + (to->tv_usec / 1000) : INFINITE;
113 if (ms == 0 && to->tv_usec)
114 ms = 1; /* At least 1 ms granularity */
1fd5e000 115
962f9a2c
CF
116 if (to)
117 select_printf ("to->tv_sec %d, to->tv_usec %d, ms %d", to->tv_sec, to->tv_usec, ms);
118 else
119 select_printf ("to NULL, ms %x", ms);
120
121 res = select (maxfds, readfds ?: allocfd_set (maxfds),
b052bf26
CF
122 writefds ?: allocfd_set (maxfds),
123 exceptfds ?: allocfd_set (maxfds), ms);
962f9a2c 124 }
b052bf26
CF
125 syscall_printf ("%R = select(%d, %p, %p, %p, %p)", res, maxfds, readfds,
126 writefds, exceptfds, to);
127 return res;
128}
1fd5e000 129
b052bf26
CF
130/* This function is arbitrarily split out from cygwin_select to avoid odd
131 gcc issues with the use of allocfd_set and improper constructor handling
132 for the sel variable. */
133static int
134select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
135 DWORD ms)
136{
45b61a88 137 int res = select_stuff::select_loop;
8d661d36 138
45b61a88
CF
139 LONGLONG start_time = gtod.msecs (); /* Record the current time for later use. */
140
b052bf26
CF
141 select_stuff sel;
142 sel.return_on_signal = 0;
143
144 /* Allocate some fd_set structures using the number of fds as a guide. */
145 fd_set *r = allocfd_set (maxfds);
146 fd_set *w = allocfd_set (maxfds);
147 fd_set *e = allocfd_set (maxfds);
148
45b61a88
CF
149 while (res == select_stuff::select_loop)
150 {
00a31243
CF
151 /* Build the select record per fd linked list and set state as
152 needed. */
45b61a88
CF
153 for (int i = 0; i < maxfds; i++)
154 if (!sel.test_and_set (i, readfds, writefds, exceptfds))
155 {
156 select_printf ("aborting due to test_and_set error");
157 return -1; /* Invalid fd, maybe? */
158 }
159 select_printf ("sel.always_ready %d", sel.always_ready);
160
161 /* Degenerate case. No fds to wait for. Just wait for time to run out
162 or signal to arrive. */
163 if (sel.start.next == NULL)
164 switch (cygwait (ms))
165 {
4ae63783 166 case WAIT_SIGNALED:
45b61a88 167 select_printf ("signal received");
2f47bbd5
CF
168 /* select() is always interrupted by a signal so set EINTR,
169 unconditionally, ignoring any SA_RESTART detection by
170 call_signal_handler(). */
171 _my_tls.call_signal_handler ();
172 set_sig_errno (EINTR);
173 res = select_stuff::select_signalled;
45b61a88 174 break;
4ae63783 175 case WAIT_CANCELED:
45b61a88
CF
176 sel.destroy ();
177 pthread::static_cancel_self ();
178 /*NOTREACHED*/
179 default:
180 res = select_stuff::select_set_zero; /* Set res to zero below. */
181 break;
182 }
183 else if (sel.always_ready || ms == 0)
00a31243
CF
184 res = 0; /* Catch any active fds via
185 sel.poll() below */
45b61a88 186 else
00a31243
CF
187 res = sel.wait (r, w, e, ms); /* wait for an fd to become
188 become active or time out */
962f9a2c 189 select_printf ("res %d", res);
abf1b600 190 if (res >= 0)
45d7b637 191 {
45b61a88
CF
192 copyfd_set (readfds, r, maxfds);
193 copyfd_set (writefds, w, maxfds);
194 copyfd_set (exceptfds, e, maxfds);
00a31243 195 /* Actually set the bit mask from sel records */
45b61a88
CF
196 res = (res == select_stuff::select_set_zero) ? 0 : sel.poll (readfds, writefds, exceptfds);
197 }
00a31243
CF
198 /* Always clean up everything here. If we're looping then build it
199 all up again. */
45b61a88
CF
200 sel.cleanup ();
201 sel.destroy ();
00a31243 202 /* Recalculate the time remaining to wait if we are going to be looping. */
45b61a88
CF
203 if (res == select_stuff::select_loop && ms != INFINITE)
204 {
205 select_printf ("recalculating ms");
206 LONGLONG now = gtod.msecs ();
207 if (now > (start_time + ms))
962f9a2c
CF
208 {
209 select_printf ("timed out after verification");
4c36016b 210 res = 0;
962f9a2c 211 }
45b61a88
CF
212 else
213 {
214 ms -= (now - start_time);
215 start_time = now;
216 select_printf ("ms now %u", ms);
217 }
45d7b637 218 }
d4f82450
CF
219 }
220
7c15768a
CF
221 if (res < -1)
222 res = -1;
d4f82450 223 return res;
1fd5e000
CF
224}
225
d02099f2
CV
226extern "C" int
227pselect(int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
228 const struct timespec *ts, const sigset_t *set)
229{
230 struct timeval tv;
70300fdb 231 sigset_t oldset = _my_tls.sigmask;
d02099f2 232
893ac8e0
CF
233 myfault efault;
234 if (efault.faulted (EFAULT))
235 return -1;
d02099f2
CV
236 if (ts)
237 {
d02099f2
CV
238 tv.tv_sec = ts->tv_sec;
239 tv.tv_usec = ts->tv_nsec / 1000;
240 }
241 if (set)
962f9a2c 242 set_signal_mask (_my_tls.sigmask, *set);
d02099f2 243 int ret = cygwin_select (maxfds, readfds, writefds, exceptfds,
05726ddd 244 ts ? &tv : NULL);
d02099f2 245 if (set)
962f9a2c 246 set_signal_mask (_my_tls.sigmask, oldset);
d02099f2
CV
247 return ret;
248}
249
5835f2cf
CF
250/* Call cleanup functions for all inspected fds. Gets rid of any
251 executing threads. */
252void
253select_stuff::cleanup ()
1fd5e000
CF
254{
255 select_record *s = &start;
256
257 select_printf ("calling cleanup routines");
258 while ((s = s->next))
259 if (s->cleanup)
5835f2cf
CF
260 {
261 s->cleanup (s, this);
262 s->cleanup = NULL;
263 }
264}
1fd5e000 265
5835f2cf 266/* Destroy all storage associated with select stuff. */
781822a6
CV
267inline void
268select_stuff::destroy ()
5835f2cf 269{
45b61a88 270 select_record *s;
1fd5e000
CF
271 select_record *snext = start.next;
272
273 select_printf ("deleting select records");
274 while ((s = snext))
275 {
276 snext = s->next;
277 delete s;
278 }
45b61a88 279 start.next = NULL;
1fd5e000
CF
280}
281
781822a6
CV
282select_stuff::~select_stuff ()
283{
284 cleanup ();
285 destroy ();
286}
287
4a84997a
CF
288#ifdef DEBUGGING
289void
290select_record::dump_select_record ()
291{
292 select_printf ("fd %d, h %p, fh %p, thread_errno %d, windows_handle %p",
293 fd, h, fh, thread_errno, windows_handle);
294 select_printf ("read_ready %d, write_ready %d, except_ready %d",
295 read_ready, write_ready, except_ready);
296 select_printf ("read_selected %d, write_selected %d, except_selected %d, except_on_write %d",
297 read_selected, write_selected, except_selected, except_on_write);
298
299 select_printf ("startup %p, peek %p, verify %p cleanup %p, next %p",
300 startup, peek, verify, cleanup, next);
301}
302#endif /*DEBUGGING*/
303
1fd5e000 304/* Add a record to the select chain */
b4fa8164 305bool
1fd5e000
CF
306select_stuff::test_and_set (int i, fd_set *readfds, fd_set *writefds,
307 fd_set *exceptfds)
308{
b4fa8164
CF
309 if (!UNIX_FD_ISSET (i, readfds) && !UNIX_FD_ISSET (i, writefds)
310 && ! UNIX_FD_ISSET (i, exceptfds))
311 return true;
312
6dadfa56 313 select_record *s = new select_record;
b4fa8164
CF
314 if (!s)
315 return false;
316
317 s->next = start.next;
318 start.next = s;
319
320 if (UNIX_FD_ISSET (i, readfds) && !cygheap->fdtab.select_read (i, this))
321 goto err;
322 if (UNIX_FD_ISSET (i, writefds) && !cygheap->fdtab.select_write (i, this))
323 goto err;
324 if (UNIX_FD_ISSET (i, exceptfds) && !cygheap->fdtab.select_except (i, this))
325 goto err; /* error */
1fd5e000
CF
326
327 if (s->read_ready || s->write_ready || s->except_ready)
476dfb65 328 always_ready = true;
1fd5e000 329
8cb359d9 330 if (s->windows_handle)
476dfb65 331 windows_used = true;
1fd5e000 332
4a84997a
CF
333#ifdef DEBUGGING
334 s->dump_select_record ();
335#endif
b4fa8164
CF
336 return true;
337
338err:
339 start.next = s->next;
340 delete s;
341 return false;
1fd5e000
CF
342}
343
1fd5e000 344/* The heart of select. Waits for an fd to do something interesting. */
45b61a88 345select_stuff::wait_states
1fd5e000
CF
346select_stuff::wait (fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
347 DWORD ms)
348{
aefbf388 349 HANDLE w4[MAXIMUM_WAIT_OBJECTS];
1fd5e000 350 select_record *s = &start;
45b61a88 351 DWORD m = 0;
1fd5e000 352
44aa2292 353 set_signal_arrived here (w4[m++]);
781822a6 354 if ((w4[m] = pthread::get_cancel_event ()) != NULL)
45b61a88 355 m++;
781822a6 356
7c15768a 357 DWORD startfds = m;
1fd5e000
CF
358 /* Loop through the select chain, starting up anything appropriate and
359 counting the number of active fds. */
360 while ((s = s->next))
361 {
fe3db6cc 362 if (m >= MAXIMUM_WAIT_OBJECTS)
b5ae313a 363 {
80a429d2 364 set_sig_errno (EINVAL);
45b61a88 365 return select_error;
b5ae313a 366 }
1fd5e000
CF
367 if (!s->startup (s, this))
368 {
169c465a 369 s->set_select_errno ();
45b61a88 370 return select_error;
1fd5e000 371 }
45b61a88 372 if (s->h != NULL)
7c15768a
CF
373 {
374 for (DWORD i = startfds; i < m; i++)
375 if (w4[i] == s->h)
376 goto next_while;
377 w4[m++] = s->h;
378 }
379next_while:;
1fd5e000
CF
380 }
381
0072fdab 382 debug_printf ("m %d, ms %u", m, ms);
45b61a88
CF
383
384 DWORD wait_ret;
385 if (!windows_used)
386 wait_ret = WaitForMultipleObjects (m, w4, FALSE, ms);
387 else
388 /* Using MWMO_INPUTAVAILABLE is the officially supported solution for
389 the problem that the call to PeekMessage disarms the queue state
390 so that a subsequent MWFMO hangs, even if there are still messages
391 in the queue. */
392 wait_ret = MsgWaitForMultipleObjectsEx (m, w4, ms,
393 QS_ALLINPUT | QS_ALLPOSTMESSAGE,
394 MWMO_INPUTAVAILABLE);
395 select_printf ("wait_ret %d. verifying", wait_ret);
396
397 wait_states res;
398 switch (wait_ret)
1fd5e000 399 {
45b61a88
CF
400 case WAIT_OBJECT_0:
401 select_printf ("signal received");
00a31243
CF
402 /* Need to get rid of everything when a signal occurs since we can't
403 be assured that a signal handler won't jump out of select entirely. */
45b61a88
CF
404 cleanup ();
405 destroy ();
2f47bbd5
CF
406 /* select() is always interrupted by a signal so set EINTR,
407 unconditionally, ignoring any SA_RESTART detection by
408 call_signal_handler(). */
409 _my_tls.call_signal_handler ();
410 set_sig_errno (EINTR);
411 res = select_signalled; /* Cause loop exit in cygwin_select */
45b61a88
CF
412 break;
413 case WAIT_FAILED:
63d9f293 414 system_printf ("WaitForMultipleObjects failed, %E");
45b61a88
CF
415 s = &start;
416 s->set_select_errno ();
417 res = select_error;
418 break;
419 case WAIT_TIMEOUT:
420 select_printf ("timed out");
abf1b600 421 res = select_set_zero;
45b61a88
CF
422 break;
423 case WAIT_OBJECT_0 + 1:
424 if (startfds > 1)
425 {
8978381c 426 cleanup ();
45b61a88
CF
427 destroy ();
428 pthread::static_cancel_self ();
429 /*NOTREACHED*/
45d7b637 430 }
45b61a88
CF
431 /* Fall through. This wasn't a cancel event. It was just a normal object
432 to wait for. */
433 default:
1fd5e000 434 s = &start;
45b61a88 435 bool gotone = false;
11a36faa 436 /* Some types of objects (e.g., consoles) wake up on "inappropriate" events
9c510edc 437 like mouse movements. The verify function will detect these situations.
915d1824
CF
438 If it returns false, then this wakeup was a false alarm and we should go
439 back to waiting. */
1fd5e000 440 while ((s = s->next))
169c465a
CF
441 if (s->saw_error ())
442 {
443 set_errno (s->saw_error ());
45b61a88
CF
444 res = select_error; /* Somebody detected an error */
445 goto out;
169c465a 446 }
fc25f200
CF
447 else if ((((wait_ret >= m && s->windows_handle) || s->h == w4[wait_ret]))
448 && s->verify (s, readfds, writefds, exceptfds))
476dfb65 449 gotone = true;
1fd5e000 450
45b61a88
CF
451 if (!gotone)
452 res = select_loop;
453 else
454 res = select_ok;
1fd5e000 455 select_printf ("gotone %d", gotone);
45b61a88 456 break;
1fd5e000 457 }
1fd5e000 458out:
8d661d36
CF
459 select_printf ("returning %d", res);
460 return res;
1fd5e000
CF
461}
462
463static int
464set_bits (select_record *me, fd_set *readfds, fd_set *writefds,
711ded6d 465 fd_set *exceptfds)
1fd5e000
CF
466{
467 int ready = 0;
ef82f76c 468 fhandler_socket *sock;
1fd5e000
CF
469 select_printf ("me %p, testing fd %d (%s)", me, me->fd, me->fh->get_name ());
470 if (me->read_selected && me->read_ready)
471 {
472 UNIX_FD_SET (me->fd, readfds);
473 ready++;
474 }
475 if (me->write_selected && me->write_ready)
476 {
477 UNIX_FD_SET (me->fd, writefds);
ef82f76c
CV
478 if (me->except_on_write && (sock = me->fh->is_socket ()))
479 {
a6099ff8
CV
480 /* Special AF_LOCAL handling. */
481 if (!me->read_ready && sock->connect_state () == connect_pending
fd5879c1
CV
482 && sock->af_local_connect ())
483 {
484 if (me->read_selected)
485 UNIX_FD_SET (me->fd, readfds);
486 sock->connect_state (connect_failed);
487 }
488 else
489 sock->connect_state (connected);
ef82f76c 490 }
1fd5e000
CF
491 ready++;
492 }
fd5879c1 493 if (me->except_selected && me->except_ready)
1fd5e000 494 {
fd5879c1 495 UNIX_FD_SET (me->fd, exceptfds);
1fd5e000
CF
496 ready++;
497 }
498 select_printf ("ready %d", ready);
499 return ready;
500}
501
476dfb65
CF
502/* Poll every fd in the select chain. Set appropriate fd in mask. */
503int
504select_stuff::poll (fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
505{
506 int n = 0;
507 select_record *s = &start;
508 while ((s = s->next))
509 n += (!s->peek || s->peek (s, true)) ?
510 set_bits (s, readfds, writefds, exceptfds) : 0;
476dfb65
CF
511 return n;
512}
513
1fd5e000 514static int
9cec3d45 515verify_true (select_record *, fd_set *, fd_set *, fd_set *)
1fd5e000
CF
516{
517 return 1;
518}
519
520static int
521verify_ok (select_record *me, fd_set *readfds, fd_set *writefds,
522 fd_set *exceptfds)
523{
524 return set_bits (me, readfds, writefds, exceptfds);
525}
526
527static int
9cec3d45 528no_startup (select_record *, select_stuff *)
1fd5e000
CF
529{
530 return 1;
531}
532
533static int
534no_verify (select_record *, fd_set *, fd_set *, fd_set *)
535{
536 return 0;
537}
538
a7a12477
CF
539static int
540pipe_data_available (int fd, fhandler_base *fh, HANDLE h, bool writing)
541{
542 IO_STATUS_BLOCK iosb = {0};
543 FILE_PIPE_LOCAL_INFORMATION fpli = {0};
544
ee766fda
CF
545 bool res;
546 if (fh->has_ongoing_io ())
547 res = false;
548 else if (NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
549 FilePipeLocalInformation))
a7a12477 550 {
ee766fda
CF
551 /* If NtQueryInformationFile fails, optimistically assume the
552 pipe is writable. This could happen if we somehow
553 inherit a pipe that doesn't permit FILE_READ_ATTRIBUTES
554 access on the write end. */
555 select_printf ("fd %d, %s, NtQueryInformationFile failed",
556 fd, fh->get_name ());
557 res = writing ? true : -1;
558 }
559 else if (!writing)
560 {
561 paranoid_printf ("fd %d, %s, read avail %u", fd, fh->get_name (),
562 fpli.ReadDataAvailable);
563 res = !!fpli.ReadDataAvailable;
a7a12477 564 }
ee766fda
CF
565 else if ((res = (fpli.WriteQuotaAvailable = (fpli.OutboundQuota -
566 fpli.ReadDataAvailable))))
567 /* If there is anything available in the pipe buffer then signal
568 that. This means that a pipe could still block since you could
569 be trying to write more to the pipe than is available in the
570 buffer but that is the hazard of select(). */
571 paranoid_printf ("fd %d, %s, write: size %lu, avail %lu", fd,
572 fh->get_name (), fpli.OutboundQuota,
573 fpli.WriteQuotaAvailable);
574 else if ((res = (fpli.OutboundQuota < PIPE_BUF &&
575 fpli.WriteQuotaAvailable == fpli.OutboundQuota)))
576 /* If we somehow inherit a tiny pipe (size < PIPE_BUF), then consider
577 the pipe writable only if it is completely empty, to minimize the
578 probability that a subsequent write will block. */
579 select_printf ("fd, %s, write tiny pipe: size %lu, avail %lu",
580 fd, fh->get_name (), fpli.OutboundQuota,
581 fpli.WriteQuotaAvailable);
665f9a59 582 return res ?: -!!(fpli.NamedPipeState & FILE_PIPE_CLOSING_STATE);
a7a12477
CF
583}
584
1fd5e000 585static int
476dfb65 586peek_pipe (select_record *s, bool from_select)
1fd5e000 587{
19085182
CF
588 HANDLE h;
589 set_handle_or_return_if_not_open (h, s);
590
1fd5e000 591 int gotone = 0;
19085182 592 fhandler_base *fh = (fhandler_base *) s->fh;
1fd5e000 593
a7a12477
CF
594 DWORD dev = fh->get_device ();
595 if (s->read_selected && dev != FH_PIPEW)
1fd5e000 596 {
41010c6a
CF
597 if (s->read_ready)
598 {
6644c628 599 select_printf ("%s, already ready for read", fh->get_name ());
41010c6a
CF
600 gotone = 1;
601 goto out;
602 }
1fd5e000 603
c0ac34fd 604 switch (fh->get_major ())
3f0b4935 605 {
38d732a1 606 case DEV_PTYM_MAJOR:
7b03b0d8
CF
607 {
608 fhandler_pty_master *fhm = (fhandler_pty_master *) fh;
609 fhm->flush_to_slave ();
610 if (fhm->need_nl)
611 {
612 gotone = s->read_ready = true;
613 goto out;
614 }
615 }
c5d03f3d
CF
616 break;
617 default:
476dfb65 618 if (fh->get_readahead_valid ())
c5d03f3d
CF
619 {
620 select_printf ("readahead");
915d1824 621 gotone = s->read_ready = true;
c5d03f3d
CF
622 goto out;
623 }
3f0b4935 624 }
35f879a6
CF
625
626 if (fh->bg_check (SIGTTIN) <= bg_eof)
627 {
915d1824 628 gotone = s->read_ready = true;
35f879a6
CF
629 goto out;
630 }
a7a12477 631 int n = pipe_data_available (s->fd, fh, h, false);
1fd5e000 632
a7a12477 633 if (n < 0)
d584454c 634 {
a7a12477
CF
635 select_printf ("read: %s, n %d", fh->get_name (), n);
636 if (s->except_selected)
637 gotone += s->except_ready = true;
638 if (s->read_selected)
639 gotone += s->read_ready = true;
d584454c 640 }
a7a12477 641 else if (n > 0)
d584454c 642 {
a7a12477
CF
643 select_printf ("read: %s, ready for read: avail %d", fh->get_name (), n);
644 gotone += s->read_ready = true;
645 }
646 if (!gotone && s->fh->hit_eof ())
647 {
648 select_printf ("read: %s, saw EOF", fh->get_name ());
649 if (s->except_selected)
650 gotone += s->except_ready = true;
651 if (s->read_selected)
652 gotone += s->read_ready = true;
d584454c 653 }
6644c628
CF
654 }
655
a7a12477
CF
656out:
657 if (s->write_selected && dev != FH_PIPER)
658 {
659 gotone += s->write_ready = pipe_data_available (s->fd, fh, h, true);
660 select_printf ("write: %s, gotone %d", fh->get_name (), gotone);
661 }
6644c628 662 return gotone;
1fd5e000
CF
663}
664
1fd5e000
CF
665static int start_thread_pipe (select_record *me, select_stuff *stuff);
666
1fd5e000
CF
667static DWORD WINAPI
668thread_pipe (void *arg)
669{
b4fa8164 670 select_pipe_info *pi = (select_pipe_info *) arg;
cfa88257 671 DWORD sleep_time = 0;
19085182 672 bool looping = true;
1fd5e000 673
19085182 674 while (looping)
1fd5e000 675 {
19085182 676 for (select_record *s = pi->start; (s = s->next); )
1fd5e000
CF
677 if (s->startup == start_thread_pipe)
678 {
476dfb65 679 if (peek_pipe (s, true))
19085182 680 looping = false;
b4fa8164 681 if (pi->stop_thread)
1fd5e000
CF
682 {
683 select_printf ("stopping");
19085182
CF
684 looping = false;
685 break;
1fd5e000
CF
686 }
687 }
19085182 688 if (!looping)
1fd5e000 689 break;
b4c53a7c
CV
690 Sleep (sleep_time >> 3);
691 if (sleep_time < 80)
9c9959a5 692 ++sleep_time;
19085182
CF
693 if (pi->stop_thread)
694 break;
1fd5e000 695 }
1fd5e000
CF
696 return 0;
697}
698
699static int
700start_thread_pipe (select_record *me, select_stuff *stuff)
701{
b4fa8164
CF
702 select_pipe_info *pi = stuff->device_specific_pipe;
703 if (pi->start)
704 me->h = *((select_pipe_info *) stuff->device_specific_pipe)->thread;
705 else
1fd5e000 706 {
b4fa8164
CF
707 pi->start = &stuff->start;
708 pi->stop_thread = false;
b9aa8149 709 pi->thread = new cygthread (thread_pipe, pi, "pipesel");
b4fa8164
CF
710 me->h = *pi->thread;
711 if (!me->h)
712 return 0;
1fd5e000 713 }
1fd5e000
CF
714 return 1;
715}
716
717static void
9cec3d45 718pipe_cleanup (select_record *, select_stuff *stuff)
1fd5e000 719{
19085182 720 select_pipe_info *pi = (select_pipe_info *) stuff->device_specific_pipe;
693581e4
CF
721 if (!pi)
722 return;
723 if (pi->thread)
1fd5e000 724 {
19085182
CF
725 pi->stop_thread = true;
726 pi->thread->detach ();
1fd5e000 727 }
693581e4
CF
728 delete pi;
729 stuff->device_specific_pipe = NULL;
1fd5e000
CF
730}
731
732select_record *
b4fa8164 733fhandler_pipe::select_read (select_stuff *ss)
1fd5e000 734{
b4fa8164
CF
735 if (!ss->device_specific_pipe
736 && (ss->device_specific_pipe = new select_pipe_info) == NULL)
737 return NULL;
b4fa8164
CF
738
739 select_record *s = ss->start.next;
1fd5e000 740 s->startup = start_thread_pipe;
1229d4f4 741 s->peek = peek_pipe;
1fd5e000 742 s->verify = verify_ok;
6644c628 743 s->cleanup = pipe_cleanup;
476dfb65
CF
744 s->read_selected = true;
745 s->read_ready = false;
1fd5e000
CF
746 return s;
747}
748
749select_record *
b4fa8164 750fhandler_pipe::select_write (select_stuff *ss)
1fd5e000 751{
b4fa8164
CF
752 if (!ss->device_specific_pipe
753 && (ss->device_specific_pipe = new select_pipe_info) == NULL)
754 return NULL;
b4fa8164 755 select_record *s = ss->start.next;
6644c628 756 s->startup = start_thread_pipe;
476dfb65 757 s->peek = peek_pipe;
6644c628
CF
758 s->verify = verify_ok;
759 s->cleanup = pipe_cleanup;
476dfb65 760 s->write_selected = true;
6644c628 761 s->write_ready = false;
1fd5e000
CF
762 return s;
763}
764
765select_record *
b4fa8164 766fhandler_pipe::select_except (select_stuff *ss)
1fd5e000 767{
b4fa8164
CF
768 if (!ss->device_specific_pipe
769 && (ss->device_specific_pipe = new select_pipe_info) == NULL)
770 return NULL;
b4fa8164 771 select_record *s = ss->start.next;
1fd5e000 772 s->startup = start_thread_pipe;
476dfb65 773 s->peek = peek_pipe;
1fd5e000
CF
774 s->verify = verify_ok;
775 s->cleanup = pipe_cleanup;
476dfb65
CF
776 s->except_selected = true;
777 s->except_ready = false;
1fd5e000
CF
778 return s;
779}
780
c7ef20e7 781select_record *
b4fa8164 782fhandler_fifo::select_read (select_stuff *ss)
c7ef20e7 783{
4c9a7726
CF
784 if (!ss->device_specific_pipe
785 && (ss->device_specific_pipe = new select_pipe_info) == NULL)
786 return NULL;
b4fa8164 787 select_record *s = ss->start.next;
c7ef20e7
CF
788 s->startup = start_thread_pipe;
789 s->peek = peek_pipe;
790 s->verify = verify_ok;
791 s->cleanup = pipe_cleanup;
792 s->read_selected = true;
793 s->read_ready = false;
794 return s;
795}
796
797select_record *
b4fa8164 798fhandler_fifo::select_write (select_stuff *ss)
c7ef20e7 799{
4c9a7726
CF
800 if (!ss->device_specific_pipe
801 && (ss->device_specific_pipe = new select_pipe_info) == NULL)
802 return NULL;
b4fa8164 803 select_record *s = ss->start.next;
c7ef20e7
CF
804 s->startup = start_thread_pipe;
805 s->peek = peek_pipe;
806 s->verify = verify_ok;
807 s->cleanup = pipe_cleanup;
808 s->write_selected = true;
809 s->write_ready = false;
810 return s;
811}
812
813select_record *
b4fa8164 814fhandler_fifo::select_except (select_stuff *ss)
c7ef20e7 815{
4c9a7726
CF
816 if (!ss->device_specific_pipe
817 && (ss->device_specific_pipe = new select_pipe_info) == NULL)
818 return NULL;
b4fa8164 819 select_record *s = ss->start.next;
c7ef20e7
CF
820 s->startup = start_thread_pipe;
821 s->peek = peek_pipe;
822 s->verify = verify_ok;
823 s->cleanup = pipe_cleanup;
824 s->except_selected = true;
825 s->except_ready = false;
826 return s;
827}
828
1fd5e000 829static int
476dfb65 830peek_console (select_record *me, bool)
1fd5e000 831{
a9867e1b 832 extern const char * get_nonascii_key (INPUT_RECORD& input_rec, char *);
1d380f59 833 fhandler_console *fh = (fhandler_console *) me->fh;
1fd5e000
CF
834
835 if (!me->read_selected)
836 return me->write_ready;
837
476dfb65 838 if (fh->get_readahead_valid ())
1fd5e000
CF
839 {
840 select_printf ("readahead");
915d1824 841 return me->read_ready = true;
1fd5e000
CF
842 }
843
41010c6a
CF
844 if (me->read_ready)
845 {
846 select_printf ("already ready");
847 return 1;
848 }
849
1fd5e000
CF
850 INPUT_RECORD irec;
851 DWORD events_read;
852 HANDLE h;
a9867e1b 853 char tmpbuf[17];
1fd5e000
CF
854 set_handle_or_return_if_not_open (h, me);
855
856 for (;;)
a7cde2b9 857 if (fh->bg_check (SIGTTIN) <= bg_eof)
915d1824 858 return me->read_ready = true;
1fd5e000
CF
859 else if (!PeekConsoleInput (h, &irec, 1, &events_read) || !events_read)
860 break;
861 else
862 {
d984eb88 863 fh->send_winch_maybe ();
c060edba 864 if (irec.EventType == KEY_EVENT)
d80999a1 865 {
c060edba
CF
866 if (irec.Event.KeyEvent.bKeyDown
867 && (irec.Event.KeyEvent.uChar.AsciiChar
868 || get_nonascii_key (irec, tmpbuf)))
915d1824 869 return me->read_ready = true;
d80999a1 870 }
c060edba
CF
871 else
872 {
c060edba 873 if (irec.EventType == MOUSE_EVENT
beeae482
CV
874 && fh->mouse_aware (irec.Event.MouseEvent))
875 return me->read_ready = true;
876 if (irec.EventType == FOCUS_EVENT && fh->focus_aware ())
c060edba
CF
877 return me->read_ready = true;
878 }
1fd5e000
CF
879
880 /* Read and discard the event */
881 ReadConsoleInput (h, &irec, 1, &events_read);
882 }
883
884 return me->write_ready;
885}
9c510edc 886
763f09b9
CF
887static int
888verify_console (select_record *me, fd_set *rfds, fd_set *wfds,
889 fd_set *efds)
890{
891 return peek_console (me, true);
892}
893
1fd5e000 894
1fd5e000 895select_record *
b4fa8164 896fhandler_console::select_read (select_stuff *ss)
1fd5e000 897{
b4fa8164
CF
898 select_record *s = ss->start.next;
899 if (!s->startup)
1fd5e000 900 {
1fd5e000 901 s->startup = no_startup;
763f09b9 902 s->verify = verify_console;
e5dd8811 903 set_cursor_maybe ();
1fd5e000
CF
904 }
905
1229d4f4 906 s->peek = peek_console;
1fd5e000 907 s->h = get_handle ();
476dfb65
CF
908 s->read_selected = true;
909 s->read_ready = false;
1fd5e000
CF
910 return s;
911}
912
913select_record *
b4fa8164 914fhandler_console::select_write (select_stuff *ss)
1fd5e000 915{
b4fa8164
CF
916 select_record *s = ss->start.next;
917 if (!s->startup)
1fd5e000 918 {
1fd5e000 919 s->startup = no_startup;
1fd5e000 920 s->verify = no_verify;
e5dd8811 921 set_cursor_maybe ();
1fd5e000
CF
922 }
923
476dfb65
CF
924 s->peek = peek_console;
925 s->write_selected = true;
926 s->write_ready = true;
1fd5e000
CF
927 return s;
928}
929
930select_record *
b4fa8164 931fhandler_console::select_except (select_stuff *ss)
1fd5e000 932{
b4fa8164
CF
933 select_record *s = ss->start.next;
934 if (!s->startup)
1fd5e000 935 {
1fd5e000 936 s->startup = no_startup;
1fd5e000 937 s->verify = no_verify;
e5dd8811 938 set_cursor_maybe ();
1fd5e000
CF
939 }
940
476dfb65
CF
941 s->peek = peek_console;
942 s->except_selected = true;
943 s->except_ready = false;
1fd5e000
CF
944 return s;
945}
946
1fd5e000 947select_record *
c75b5b2d 948fhandler_pty_common::select_read (select_stuff *ss)
1fd5e000 949{
e446d6d0
CF
950 if (!ss->device_specific_pipe
951 && (ss->device_specific_pipe = new select_pipe_info) == NULL)
952 return NULL;
953
954 select_record *s = ss->start.next;
955 s->startup = start_thread_pipe;
956 s->peek = peek_pipe;
957 s->verify = verify_ok;
958 s->cleanup = pipe_cleanup;
959 s->read_selected = true;
960 s->read_ready = false;
961 return s;
1fd5e000
CF
962}
963
964select_record *
c75b5b2d 965fhandler_pty_common::select_write (select_stuff *ss)
1fd5e000 966{
e446d6d0
CF
967 if (!ss->device_specific_pipe
968 && (ss->device_specific_pipe = new select_pipe_info) == NULL)
969 return NULL;
970 select_record *s = ss->start.next;
971 s->startup = start_thread_pipe;
972 s->peek = peek_pipe;
973 s->verify = verify_ok;
974 s->cleanup = pipe_cleanup;
975 s->write_selected = true;
976 s->write_ready = false;
977 return s;
1fd5e000
CF
978}
979
980select_record *
c75b5b2d 981fhandler_pty_common::select_except (select_stuff *ss)
1fd5e000 982{
e446d6d0
CF
983 if (!ss->device_specific_pipe
984 && (ss->device_specific_pipe = new select_pipe_info) == NULL)
985 return NULL;
986 select_record *s = ss->start.next;
987 s->startup = start_thread_pipe;
988 s->peek = peek_pipe;
989 s->verify = verify_ok;
990 s->cleanup = pipe_cleanup;
991 s->except_selected = true;
992 s->except_ready = false;
993 return s;
1fd5e000
CF
994}
995
5e8e21d9
ED
996static int
997verify_tty_slave (select_record *me, fd_set *readfds, fd_set *writefds,
998 fd_set *exceptfds)
999{
bd139e52 1000 if (IsEventSignalled (me->h))
915d1824 1001 me->read_ready = true;
5e8e21d9
ED
1002 return set_bits (me, readfds, writefds, exceptfds);
1003}
1004
1005select_record *
c75b5b2d 1006fhandler_pty_slave::select_read (select_stuff *ss)
5e8e21d9 1007{
b4fa8164 1008 select_record *s = ss->start.next;
5e8e21d9
ED
1009 s->h = input_available_event;
1010 s->startup = no_startup;
1229d4f4 1011 s->peek = peek_pipe;
5e8e21d9 1012 s->verify = verify_tty_slave;
476dfb65
CF
1013 s->read_selected = true;
1014 s->read_ready = false;
5e8e21d9
ED
1015 s->cleanup = NULL;
1016 return s;
1017}
1018
1fd5e000 1019select_record *
b4fa8164 1020fhandler_dev_null::select_read (select_stuff *ss)
1fd5e000 1021{
b4fa8164
CF
1022 select_record *s = ss->start.next;
1023 if (!s->startup)
1fd5e000 1024 {
1fd5e000 1025 s->startup = no_startup;
1fd5e000
CF
1026 s->verify = no_verify;
1027 }
1028 s->h = get_handle ();
476dfb65
CF
1029 s->read_selected = true;
1030 s->read_ready = true;
1fd5e000
CF
1031 return s;
1032}
1033
1034select_record *
b4fa8164 1035fhandler_dev_null::select_write (select_stuff *ss)
1fd5e000 1036{
b4fa8164
CF
1037 select_record *s = ss->start.next;
1038 if (!s->startup)
1fd5e000 1039 {
1fd5e000 1040 s->startup = no_startup;
1fd5e000
CF
1041 s->verify = no_verify;
1042 }
1043 s->h = get_handle ();
476dfb65
CF
1044 s->write_selected = true;
1045 s->write_ready = true;
1fd5e000
CF
1046 return s;
1047}
1048
1049select_record *
b4fa8164 1050fhandler_dev_null::select_except (select_stuff *ss)
1fd5e000 1051{
b4fa8164
CF
1052 select_record *s = ss->start.next;
1053 if (!s->startup)
1fd5e000 1054 {
1fd5e000 1055 s->startup = no_startup;
1fd5e000
CF
1056 s->verify = no_verify;
1057 }
1058 s->h = get_handle ();
476dfb65 1059 s->except_selected = true;
04843bf4 1060 s->except_ready = false;
1fd5e000
CF
1061 return s;
1062}
1063
1064static int start_thread_serial (select_record *me, select_stuff *stuff);
1065
1fd5e000 1066static int
476dfb65 1067peek_serial (select_record *s, bool)
1fd5e000 1068{
1fd5e000
CF
1069 COMSTAT st;
1070
1d380f59 1071 fhandler_serial *fh = (fhandler_serial *) s->fh;
1fd5e000
CF
1072
1073 if (fh->get_readahead_valid () || fh->overlapped_armed < 0)
915d1824 1074 return s->read_ready = true;
1fd5e000
CF
1075
1076 select_printf ("fh->overlapped_armed %d", fh->overlapped_armed);
1077
1078 HANDLE h;
1079 set_handle_or_return_if_not_open (h, s);
1080 int ready = 0;
41010c6a 1081
cb7e1879 1082 if ((s->read_selected && s->read_ready) || (s->write_selected && s->write_ready))
41010c6a
CF
1083 {
1084 select_printf ("already ready");
1085 ready = 1;
1086 goto out;
1087 }
1088
9895091d
CF
1089 /* This is apparently necessary for the com0com driver.
1090 See: http://cygwin.com/ml/cygwin/2009-01/msg00667.html */
1091 SetCommMask (h, 0);
1092
0c55f6ed 1093 SetCommMask (h, EV_RXCHAR);
1fd5e000
CF
1094
1095 if (!fh->overlapped_armed)
1096 {
1fd5e000
CF
1097 COMSTAT st;
1098
1099 ResetEvent (fh->io_status.hEvent);
1100
40139114 1101 if (!ClearCommError (h, &fh->ev, &st))
1fd5e000
CF
1102 {
1103 debug_printf ("ClearCommError");
1104 goto err;
1105 }
1106 else if (st.cbInQue)
915d1824 1107 return s->read_ready = true;
40139114 1108 else if (WaitCommEvent (h, &fh->ev, &fh->io_status))
915d1824 1109 return s->read_ready = true;
1fd5e000
CF
1110 else if (GetLastError () == ERROR_IO_PENDING)
1111 fh->overlapped_armed = 1;
1112 else
1113 {
1114 debug_printf ("WaitCommEvent");
1115 goto err;
1116 }
1117 }
1118
79e741ef 1119 switch (WaitForSingleObject (fh->io_status.hEvent, 10L))
1fd5e000
CF
1120 {
1121 case WAIT_OBJECT_0:
40139114 1122 if (!ClearCommError (h, &fh->ev, &st))
b0e82b74
CF
1123 {
1124 debug_printf ("ClearCommError");
1125 goto err;
1126 }
1fd5e000 1127 else if (!st.cbInQue)
79e741ef 1128 Sleep (10L);
1fd5e000
CF
1129 else
1130 {
915d1824 1131 return s->read_ready = true;
1fd5e000
CF
1132 select_printf ("got something");
1133 }
1fd5e000 1134 break;
1fd5e000 1135 case WAIT_TIMEOUT:
1fd5e000
CF
1136 break;
1137 default:
1fd5e000
CF
1138 debug_printf ("WaitForMultipleObjects");
1139 goto err;
1140 }
1141
41010c6a 1142out:
1fd5e000
CF
1143 return ready;
1144
1145err:
1146 if (GetLastError () == ERROR_OPERATION_ABORTED)
1147 {
1148 select_printf ("operation aborted");
1149 return ready;
1150 }
1151
169c465a 1152 s->set_select_errno ();
1fd5e000
CF
1153 select_printf ("error %E");
1154 return -1;
1155}
1156
1157static DWORD WINAPI
1158thread_serial (void *arg)
1159{
b4fa8164 1160 select_serial_info *si = (select_serial_info *) arg;
19085182 1161 bool looping = true;
1fd5e000 1162
19085182
CF
1163 while (looping)
1164 for (select_record *s = si->start; (s = s->next); )
1165 if (s->startup != start_thread_serial)
1166 continue;
1167 else
1fd5e000 1168 {
19085182
CF
1169 if (peek_serial (s, true))
1170 looping = false;
1171 if (si->stop_thread)
1172 {
1173 select_printf ("stopping");
1174 looping = false;
1175 break;
1176 }
1fd5e000 1177 }
1fd5e000
CF
1178
1179 select_printf ("exiting");
1180 return 0;
1181}
1182
1183static int
1184start_thread_serial (select_record *me, select_stuff *stuff)
1185{
7ac61736 1186 if (stuff->device_specific_serial)
b4fa8164
CF
1187 me->h = *((select_serial_info *) stuff->device_specific_serial)->thread;
1188 else
1fd5e000 1189 {
b4fa8164
CF
1190 select_serial_info *si = new select_serial_info;
1191 si->start = &stuff->start;
1192 si->stop_thread = false;
b9aa8149 1193 si->thread = new cygthread (thread_serial, si, "sersel");
b4fa8164
CF
1194 me->h = *si->thread;
1195 stuff->device_specific_serial = si;
1fd5e000 1196 }
1fd5e000
CF
1197 return 1;
1198}
1199
1200static void
9cec3d45 1201serial_cleanup (select_record *, select_stuff *stuff)
1fd5e000 1202{
b4fa8164 1203 select_serial_info *si = (select_serial_info *) stuff->device_specific_serial;
2f9c2713
CF
1204 if (!si)
1205 return;
1206 if (si->thread)
1fd5e000 1207 {
b4fa8164 1208 si->stop_thread = true;
b6bd7037 1209 si->thread->detach ();
1fd5e000 1210 }
2f9c2713
CF
1211 delete si;
1212 stuff->device_specific_serial = NULL;
1fd5e000
CF
1213}
1214
1fd5e000 1215select_record *
b4fa8164 1216fhandler_serial::select_read (select_stuff *ss)
1fd5e000 1217{
b4fa8164
CF
1218 select_record *s = ss->start.next;
1219 if (!s->startup)
1fd5e000 1220 {
1fd5e000 1221 s->startup = start_thread_serial;
1fd5e000
CF
1222 s->verify = verify_ok;
1223 s->cleanup = serial_cleanup;
1224 }
1229d4f4 1225 s->peek = peek_serial;
476dfb65
CF
1226 s->read_selected = true;
1227 s->read_ready = false;
1fd5e000
CF
1228 return s;
1229}
1230
1231select_record *
b4fa8164 1232fhandler_serial::select_write (select_stuff *ss)
1fd5e000 1233{
b4fa8164
CF
1234 select_record *s = ss->start.next;
1235 if (!s->startup)
1fd5e000 1236 {
1fd5e000 1237 s->startup = no_startup;
1fd5e000
CF
1238 s->verify = verify_ok;
1239 }
476dfb65 1240 s->peek = peek_serial;
1fd5e000 1241 s->h = get_handle ();
476dfb65
CF
1242 s->write_selected = true;
1243 s->write_ready = true;
1fd5e000
CF
1244 return s;
1245}
1246
1247select_record *
b4fa8164 1248fhandler_serial::select_except (select_stuff *ss)
1fd5e000 1249{
b4fa8164
CF
1250 select_record *s = ss->start.next;
1251 if (!s->startup)
1fd5e000 1252 {
1fd5e000 1253 s->startup = no_startup;
1fd5e000
CF
1254 s->verify = verify_ok;
1255 }
1256 s->h = NULL;
476dfb65
CF
1257 s->peek = peek_serial;
1258 s->except_selected = false; // Can't do this
1259 s->except_ready = false;
1fd5e000
CF
1260 return s;
1261}
1262
1fd5e000 1263select_record *
b4fa8164 1264fhandler_base::select_read (select_stuff *ss)
1fd5e000 1265{
b4fa8164
CF
1266 select_record *s = ss->start.next;
1267 if (!s->startup)
1fd5e000 1268 {
1fd5e000 1269 s->startup = no_startup;
1fd5e000
CF
1270 s->verify = verify_ok;
1271 }
1272 s->h = get_handle ();
476dfb65
CF
1273 s->read_selected = true;
1274 s->read_ready = true;
1fd5e000
CF
1275 return s;
1276}
1277
1278select_record *
b4fa8164 1279fhandler_base::select_write (select_stuff *ss)
1fd5e000 1280{
b4fa8164
CF
1281 select_record *s = ss->start.next;
1282 if (!s->startup)
1fd5e000 1283 {
1fd5e000 1284 s->startup = no_startup;
1fd5e000
CF
1285 s->verify = verify_ok;
1286 }
1287 s->h = get_handle ();
476dfb65
CF
1288 s->write_selected = true;
1289 s->write_ready = true;
1fd5e000
CF
1290 return s;
1291}
1292
1293select_record *
b4fa8164 1294fhandler_base::select_except (select_stuff *ss)
1fd5e000 1295{
b4fa8164
CF
1296 select_record *s = ss->start.next;
1297 if (!s->startup)
1fd5e000 1298 {
1fd5e000 1299 s->startup = no_startup;
1fd5e000
CF
1300 s->verify = verify_ok;
1301 }
1302 s->h = NULL;
476dfb65
CF
1303 s->except_selected = true;
1304 s->except_ready = false;
1fd5e000
CF
1305 return s;
1306}
1307
1fd5e000 1308static int
476dfb65 1309peek_socket (select_record *me, bool)
1fd5e000 1310{
70e476d2
CV
1311 fhandler_socket *fh = (fhandler_socket *) me->fh;
1312 long events;
fd5879c1
CV
1313 /* Don't play with the settings again, unless having taken a deep look into
1314 Richard W. Stevens Network Programming book. Thank you. */
1315 long evt_mask = (me->read_selected ? (FD_READ | FD_ACCEPT | FD_CLOSE) : 0)
1316 | (me->write_selected ? (FD_WRITE | FD_CONNECT | FD_CLOSE) : 0)
1317 | (me->except_selected ? FD_OOB : 0);
70e476d2
CV
1318 int ret = fh->evaluate_events (evt_mask, events, false);
1319 if (me->read_selected)
fd5879c1 1320 me->read_ready |= ret || !!(events & (FD_READ | FD_ACCEPT | FD_CLOSE));
70e476d2 1321 if (me->write_selected)
fd5879c1 1322 me->write_ready |= ret || !!(events & (FD_WRITE | FD_CONNECT | FD_CLOSE));
70e476d2 1323 if (me->except_selected)
fd5879c1 1324 me->except_ready |= !!(events & FD_OOB);
70e476d2 1325
fd5879c1
CV
1326 select_printf ("read_ready: %d, write_ready: %d, except_ready: %d",
1327 me->read_ready, me->write_ready, me->except_ready);
fe00cca9 1328 return me->read_ready || me->write_ready || me->except_ready;
1fd5e000
CF
1329}
1330
1fd5e000
CF
1331static int start_thread_socket (select_record *, select_stuff *);
1332
1333static DWORD WINAPI
1334thread_socket (void *arg)
1335{
b4fa8164 1336 select_socket_info *si = (select_socket_info *) arg;
023c2582
CV
1337 DWORD timeout = (si->num_w4 <= MAXIMUM_WAIT_OBJECTS)
1338 ? INFINITE
1339 : (64 / (roundup2 (si->num_w4, MAXIMUM_WAIT_OBJECTS)
1340 / MAXIMUM_WAIT_OBJECTS));
70e476d2 1341 bool event = false;
1fd5e000 1342
abf1b600 1343 select_printf ("stuff_start %p, timeout %u", si->start, timeout);
70e476d2
CV
1344 while (!event)
1345 {
1346 for (select_record *s = si->start; (s = s->next); )
1347 if (s->startup == start_thread_socket)
1348 if (peek_socket (s, false))
1349 event = true;
1350 if (!event)
023c2582 1351 for (int i = 0; i < si->num_w4; i += MAXIMUM_WAIT_OBJECTS)
75543537 1352 switch (WaitForMultipleObjects (MIN (si->num_w4 - i,
9565e233
CV
1353 MAXIMUM_WAIT_OBJECTS),
1354 si->w4 + i, FALSE, timeout))
1fd5e000 1355 {
70e476d2
CV
1356 case WAIT_FAILED:
1357 goto out;
023c2582
CV
1358 case WAIT_TIMEOUT:
1359 continue;
9565e233
CV
1360 case WAIT_OBJECT_0:
1361 if (!i) /* Socket event set. */
510a85cb 1362 goto out;
023c2582 1363 /*FALLTHRU*/
70e476d2
CV
1364 default:
1365 break;
1fd5e000 1366 }
70e476d2
CV
1367 }
1368out:
1369 select_printf ("leaving thread_socket");
1fd5e000
CF
1370 return 0;
1371}
1372
023c2582
CV
1373static inline bool init_tls_select_info () __attribute__ ((always_inline));
1374static inline bool
1375init_tls_select_info ()
1376{
1377 if (!_my_tls.locals.select.sockevt)
1378 {
1379 _my_tls.locals.select.sockevt = CreateEvent (&sec_none_nih, TRUE, FALSE,
1380 NULL);
1381 if (!_my_tls.locals.select.sockevt)
1382 return false;
1383 }
1384 if (!_my_tls.locals.select.ser_num)
1385 {
1386 _my_tls.locals.select.ser_num
1387 = (LONG *) malloc (MAXIMUM_WAIT_OBJECTS * sizeof (LONG));
1388 if (!_my_tls.locals.select.ser_num)
1389 return false;
1390 _my_tls.locals.select.w4
1391 = (HANDLE *) malloc (MAXIMUM_WAIT_OBJECTS * sizeof (HANDLE));
1392 if (!_my_tls.locals.select.w4)
1393 {
1394 free (_my_tls.locals.select.ser_num);
1395 _my_tls.locals.select.ser_num = NULL;
1396 return false;
1397 }
1398 _my_tls.locals.select.max_w4 = MAXIMUM_WAIT_OBJECTS;
1399 }
1400 return true;
1401}
1402
1fd5e000
CF
1403static int
1404start_thread_socket (select_record *me, select_stuff *stuff)
1405{
b4fa8164 1406 select_socket_info *si;
1fd5e000 1407
b4fa8164 1408 if ((si = (select_socket_info *) stuff->device_specific_socket))
1fd5e000 1409 {
b6bd7037 1410 me->h = *si->thread;
1fd5e000
CF
1411 return 1;
1412 }
1413
b4fa8164 1414 si = new select_socket_info;
023c2582
CV
1415
1416 if (!init_tls_select_info ())
9565e233 1417 return 0;
023c2582
CV
1418
1419 si->ser_num = _my_tls.locals.select.ser_num;
1420 si->w4 = _my_tls.locals.select.w4;
1421
1422 si->w4[0] = _my_tls.locals.select.sockevt;
70e476d2 1423 si->num_w4 = 1;
023c2582
CV
1424
1425 select_record *s = &stuff->start;
1fd5e000
CF
1426 while ((s = s->next))
1427 if (s->startup == start_thread_socket)
1428 {
8f713b6b
CV
1429 /* No event/socket should show up multiple times. Every socket
1430 is uniquely identified by its serial number in the global
1431 wsock_events record. */
9565e233 1432 const LONG ser_num = ((fhandler_socket *) s->fh)->serial_number ();
70e476d2 1433 for (int i = 1; i < si->num_w4; ++i)
8f713b6b 1434 if (si->ser_num[i] == ser_num)
70e476d2 1435 goto continue_outer_loop;
023c2582 1436 if (si->num_w4 >= _my_tls.locals.select.max_w4)
8f713b6b 1437 {
9565e233 1438 LONG *nser = (LONG *) realloc (si->ser_num,
023c2582
CV
1439 (_my_tls.locals.select.max_w4
1440 + MAXIMUM_WAIT_OBJECTS)
9565e233
CV
1441 * sizeof (LONG));
1442 if (!nser)
1443 return 0;
023c2582 1444 _my_tls.locals.select.ser_num = si->ser_num = nser;
9565e233 1445 HANDLE *nw4 = (HANDLE *) realloc (si->w4,
023c2582
CV
1446 (_my_tls.locals.select.max_w4
1447 + MAXIMUM_WAIT_OBJECTS)
9565e233
CV
1448 * sizeof (HANDLE));
1449 if (!nw4)
1450 return 0;
023c2582
CV
1451 _my_tls.locals.select.w4 = si->w4 = nw4;
1452 _my_tls.locals.select.max_w4 += MAXIMUM_WAIT_OBJECTS;
8f713b6b 1453 }
9565e233
CV
1454 si->ser_num[si->num_w4] = ser_num;
1455 si->w4[si->num_w4++] = ((fhandler_socket *) s->fh)->wsock_event ();
70e476d2
CV
1456 continue_outer_loop:
1457 ;
1458 }
b4fa8164 1459 stuff->device_specific_socket = si;
1fd5e000
CF
1460 si->start = &stuff->start;
1461 select_printf ("stuff_start %p", &stuff->start);
b9aa8149 1462 si->thread = new cygthread (thread_socket, si, "socksel");
b6bd7037
CF
1463 me->h = *si->thread;
1464 return 1;
1fd5e000
CF
1465}
1466
1467void
9cec3d45 1468socket_cleanup (select_record *, select_stuff *stuff)
1fd5e000 1469{
b4fa8164 1470 select_socket_info *si = (select_socket_info *) stuff->device_specific_socket;
1fd5e000 1471 select_printf ("si %p si->thread %p", si, si ? si->thread : NULL);
2f9c2713
CF
1472 if (!si)
1473 return;
1474 if (si->thread)
1fd5e000 1475 {
70e476d2 1476 SetEvent (si->w4[0]);
1fd5e000 1477 /* Wait for thread to go away */
b6bd7037 1478 si->thread->detach ();
70e476d2 1479 ResetEvent (si->w4[0]);
1fd5e000 1480 }
2f9c2713
CF
1481 delete si;
1482 stuff->device_specific_socket = NULL;
1fd5e000
CF
1483 select_printf ("returning");
1484}
1485
1486select_record *
b4fa8164 1487fhandler_socket::select_read (select_stuff *ss)
1fd5e000 1488{
b4fa8164
CF
1489 select_record *s = ss->start.next;
1490 if (!s->startup)
1fd5e000 1491 {
1fd5e000 1492 s->startup = start_thread_socket;
1fd5e000
CF
1493 s->verify = verify_true;
1494 s->cleanup = socket_cleanup;
1495 }
1229d4f4 1496 s->peek = peek_socket;
5835f2cf 1497 s->read_ready = saw_shutdown_read ();
476dfb65 1498 s->read_selected = true;
1fd5e000
CF
1499 return s;
1500}
1501
1502select_record *
b4fa8164 1503fhandler_socket::select_write (select_stuff *ss)
1fd5e000 1504{
b4fa8164
CF
1505 select_record *s = ss->start.next;
1506 if (!s->startup)
1fd5e000 1507 {
1fd5e000 1508 s->startup = start_thread_socket;
1fd5e000
CF
1509 s->verify = verify_true;
1510 s->cleanup = socket_cleanup;
1511 }
476dfb65 1512 s->peek = peek_socket;
56551a9b 1513 s->write_ready = saw_shutdown_write () || connect_state () == unconnected;
476dfb65 1514 s->write_selected = true;
04843bf4 1515 if (connect_state () != unconnected)
6bb769ef
CV
1516 {
1517 s->except_ready = saw_shutdown_write () || saw_shutdown_read ();
1518 s->except_on_write = true;
1519 }
1fd5e000
CF
1520 return s;
1521}
1522
1523select_record *
b4fa8164 1524fhandler_socket::select_except (select_stuff *ss)
1fd5e000 1525{
b4fa8164
CF
1526 select_record *s = ss->start.next;
1527 if (!s->startup)
1fd5e000 1528 {
1fd5e000 1529 s->startup = start_thread_socket;
1fd5e000
CF
1530 s->verify = verify_true;
1531 s->cleanup = socket_cleanup;
1532 }
476dfb65 1533 s->peek = peek_socket;
5835f2cf
CF
1534 /* FIXME: Is this right? Should these be used as criteria for except? */
1535 s->except_ready = saw_shutdown_write () || saw_shutdown_read ();
476dfb65 1536 s->except_selected = true;
1fd5e000
CF
1537 return s;
1538}
1539
1540static int
476dfb65 1541peek_windows (select_record *me, bool)
1fd5e000
CF
1542{
1543 MSG m;
1544 HANDLE h;
1545 set_handle_or_return_if_not_open (h, me);
41010c6a
CF
1546
1547 if (me->read_selected && me->read_ready)
1548 return 1;
1549
79e741ef 1550 if (PeekMessageW (&m, (HWND) h, 0, 0, PM_NOREMOVE))
1fd5e000 1551 {
476dfb65 1552 me->read_ready = true;
fc25f200 1553 select_printf ("window %d(%p) ready", me->fd, h);
1fd5e000
CF
1554 return 1;
1555 }
1556
fc25f200 1557 select_printf ("window %d(%p) not ready", me->fd, h);
1fd5e000
CF
1558 return me->write_ready;
1559}
1560
763f09b9
CF
1561static int
1562verify_windows (select_record *me, fd_set *rfds, fd_set *wfds,
1563 fd_set *efds)
1564{
1565 return peek_windows (me, true);
1566}
1567
1fd5e000 1568select_record *
b4fa8164 1569fhandler_windows::select_read (select_stuff *ss)
1fd5e000 1570{
b4fa8164
CF
1571 select_record *s = ss->start.next;
1572 if (!s->startup)
1fd5e000 1573 {
1fd5e000 1574 s->startup = no_startup;
1fd5e000 1575 }
763f09b9 1576 s->verify = verify_windows;
1229d4f4 1577 s->peek = peek_windows;
476dfb65
CF
1578 s->read_selected = true;
1579 s->read_ready = false;
1fd5e000 1580 s->h = get_handle ();
476dfb65 1581 s->windows_handle = true;
1fd5e000
CF
1582 return s;
1583}
1584
1585select_record *
b4fa8164 1586fhandler_windows::select_write (select_stuff *ss)
1fd5e000 1587{
b4fa8164
CF
1588 select_record *s = ss->start.next;
1589 if (!s->startup)
1fd5e000 1590 {
1fd5e000 1591 s->startup = no_startup;
1fd5e000
CF
1592 s->verify = verify_ok;
1593 }
476dfb65 1594 s->peek = peek_windows;
1fd5e000 1595 s->h = get_handle ();
476dfb65
CF
1596 s->write_selected = true;
1597 s->write_ready = true;
1598 s->windows_handle = true;
1fd5e000
CF
1599 return s;
1600}
1601
1602select_record *
b4fa8164 1603fhandler_windows::select_except (select_stuff *ss)
1fd5e000 1604{
b4fa8164
CF
1605 select_record *s = ss->start.next;
1606 if (!s->startup)
1fd5e000 1607 {
1fd5e000 1608 s->startup = no_startup;
1fd5e000
CF
1609 s->verify = verify_ok;
1610 }
476dfb65 1611 s->peek = peek_windows;
1fd5e000 1612 s->h = get_handle ();
476dfb65 1613 s->except_selected = true;
04843bf4 1614 s->except_ready = false;
476dfb65 1615 s->windows_handle = true;
1fd5e000
CF
1616 return s;
1617}
13505ca8
CV
1618
1619static int
1620peek_mailslot (select_record *me, bool)
1621{
1622 HANDLE h;
1623 set_handle_or_return_if_not_open (h, me);
1624
1625 if (me->read_selected && me->read_ready)
1626 return 1;
1627 DWORD msgcnt = 0;
1628 if (!GetMailslotInfo (h, NULL, NULL, &msgcnt, NULL))
1629 {
1630 select_printf ("mailslot %d(%p) error %E", me->fd, h);
1631 return 1;
1632 }
1633 if (msgcnt > 0)
1634 {
1635 me->read_ready = true;
1636 select_printf ("mailslot %d(%p) ready", me->fd, h);
1637 return 1;
1638 }
1639 select_printf ("mailslot %d(%p) not ready", me->fd, h);
1640 return 0;
1641}
1642
1643static int
1644verify_mailslot (select_record *me, fd_set *rfds, fd_set *wfds,
1645 fd_set *efds)
1646{
1647 return peek_mailslot (me, true);
1648}
1649
1650static int start_thread_mailslot (select_record *me, select_stuff *stuff);
1651
13505ca8
CV
1652static DWORD WINAPI
1653thread_mailslot (void *arg)
1654{
b4fa8164 1655 select_mailslot_info *mi = (select_mailslot_info *) arg;
13505ca8 1656 bool gotone = false;
cfa88257 1657 DWORD sleep_time = 0;
13505ca8
CV
1658
1659 for (;;)
1660 {
1661 select_record *s = mi->start;
1662 while ((s = s->next))
1663 if (s->startup == start_thread_mailslot)
1664 {
1665 if (peek_mailslot (s, true))
1666 gotone = true;
b4fa8164 1667 if (mi->stop_thread)
13505ca8
CV
1668 {
1669 select_printf ("stopping");
1670 goto out;
1671 }
1672 }
1673 /* Paranoid check */
b4fa8164 1674 if (mi->stop_thread)
13505ca8
CV
1675 {
1676 select_printf ("stopping from outer loop");
1677 break;
1678 }
1679 if (gotone)
1680 break;
b4c53a7c
CV
1681 Sleep (sleep_time >> 3);
1682 if (sleep_time < 80)
9c9959a5 1683 ++sleep_time;
13505ca8
CV
1684 }
1685out:
1686 return 0;
1687}
1688
1689static int
1690start_thread_mailslot (select_record *me, select_stuff *stuff)
1691{
1692 if (stuff->device_specific_mailslot)
1693 {
b4fa8164 1694 me->h = *((select_mailslot_info *) stuff->device_specific_mailslot)->thread;
13505ca8
CV
1695 return 1;
1696 }
b4fa8164 1697 select_mailslot_info *mi = new select_mailslot_info;
13505ca8 1698 mi->start = &stuff->start;
b4fa8164 1699 mi->stop_thread = false;
b9aa8149 1700 mi->thread = new cygthread (thread_mailslot, mi, "mailsel");
13505ca8
CV
1701 me->h = *mi->thread;
1702 if (!me->h)
1703 return 0;
b4fa8164 1704 stuff->device_specific_mailslot = mi;
13505ca8
CV
1705 return 1;
1706}
1707
1708static void
1709mailslot_cleanup (select_record *, select_stuff *stuff)
1710{
b4fa8164 1711 select_mailslot_info *mi = (select_mailslot_info *) stuff->device_specific_mailslot;
2f9c2713
CF
1712 if (!mi)
1713 return;
1714 if (mi->thread)
13505ca8 1715 {
b4fa8164 1716 mi->stop_thread = true;
13505ca8 1717 mi->thread->detach ();
13505ca8 1718 }
2f9c2713
CF
1719 delete mi;
1720 stuff->device_specific_mailslot = NULL;
13505ca8
CV
1721}
1722
1723select_record *
b4fa8164 1724fhandler_mailslot::select_read (select_stuff *ss)
13505ca8 1725{
b4fa8164 1726 select_record *s = ss->start.next;
13505ca8
CV
1727 s->startup = start_thread_mailslot;
1728 s->peek = peek_mailslot;
1729 s->verify = verify_mailslot;
1730 s->cleanup = mailslot_cleanup;
1731 s->read_selected = true;
1732 s->read_ready = false;
1733 return s;
1734}
This page took 0.762249 seconds and 5 git commands to generate.