]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/select.cc
revert erroneous checkin
[newlib-cygwin.git] / winsup / cygwin / select.cc
CommitLineData
1fd5e000
CF
1/* select.cc
2
cec48792 3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
1fd5e000
CF
4
5 Written by Christopher Faylor of Cygnus Solutions
6 cgf@cygnus.com
7
8This file is part of Cygwin.
9
10This software is a copyrighted work licensed under the terms of the
11Cygwin license. Please consult the file "CYGWIN_LICENSE" for
12details. */
13
1cda1322
CF
14/* The following line means that the BSD socket definitions for
15 fd_set, FD_ISSET etc. are used in this file. */
1fd5e000
CF
16
17#define __INSIDE_CYGWIN_NET__
1fd5e000 18
4c8d72de 19#include "winsup.h"
1fd5e000
CF
20#include <sys/socket.h>
21#include <stdlib.h>
22#include <sys/time.h>
23
4c8d72de
DD
24#include <wingdi.h>
25#include <winuser.h>
1fd5e000
CF
26#include <netdb.h>
27#include <unistd.h>
6644c628 28#include <limits.h>
a1299ba5 29#define USE_SYS_TYPES_FD_SET
1fd5e000
CF
30#include <winsock.h>
31#include "select.h"
9e2baf8d 32#include "cygerrno.h"
6b91b8d5 33#include "security.h"
47063f00 34#include "path.h"
7ac61736 35#include "fhandler.h"
bccd5e0d 36#include "dtable.h"
0381fec6 37#include "cygheap.h"
bccd5e0d
CF
38#include "sigproc.h"
39#include "perthread.h"
29ac7f89 40#include "tty.h"
b6bd7037 41#include "cygthread.h"
6644c628 42#include "ntdll.h"
1cda1322
CF
43#include "cygtls.h"
44#include <asm/byteorder.h>
1fd5e000
CF
45
46/*
47 * All these defines below should be in sys/types.h
48 * but because of the includes above, they may not have
49 * been included. We create special UNIX_xxxx versions here.
50 */
51
52#ifndef NBBY
53#define NBBY 8 /* number of bits in a byte */
54#endif /* NBBY */
55
56/*
57 * Select uses bit masks of file descriptors in longs.
58 * These macros manipulate such bit fields (the filesystem macros use chars).
59 * FD_SETSIZE may be defined by the user, but the default here
60 * should be >= NOFILE (param.h).
61 */
62
63typedef long fd_mask;
64#define UNIX_NFDBITS (sizeof (fd_mask) * NBBY) /* bits per mask */
65#ifndef unix_howmany
66#define unix_howmany(x,y) (((x)+((y)-1))/(y))
67#endif
68
69#define unix_fd_set fd_set
70
a1299ba5 71#define NULL_fd_set ((fd_set *) NULL)
1fd5e000 72#define sizeof_fd_set(n) \
c90e1cf1 73 ((unsigned) (NULL_fd_set->fds_bits + unix_howmany ((n), UNIX_NFDBITS)))
1fd5e000
CF
74#define UNIX_FD_SET(n, p) \
75 ((p)->fds_bits[(n)/UNIX_NFDBITS] |= (1L << ((n) % UNIX_NFDBITS)))
76#define UNIX_FD_CLR(n, p) \
77 ((p)->fds_bits[(n)/UNIX_NFDBITS] &= ~(1L << ((n) % UNIX_NFDBITS)))
78#define UNIX_FD_ISSET(n, p) \
79 ((p)->fds_bits[(n)/UNIX_NFDBITS] & (1L << ((n) % UNIX_NFDBITS)))
80#define UNIX_FD_ZERO(p, n) \
81 bzero ((caddr_t)(p), sizeof_fd_set ((n)))
82
0072fdab 83#define allocfd_set(n) ((fd_set *) memset (alloca (sizeof_fd_set (n)), 0, sizeof_fd_set (n)))
1fd5e000
CF
84#define copyfd_set(to, from, n) memcpy (to, from, sizeof_fd_set (n));
85
1fd5e000
CF
86#define set_handle_or_return_if_not_open(h, s) \
87 h = (s)->fh->get_handle (); \
0381fec6 88 if (cygheap->fdtab.not_open ((s)->fd)) \
1fd5e000 89 { \
476dfb65 90 (s)->saw_error = true; \
80a429d2 91 set_sig_errno (EBADF); \
1fd5e000
CF
92 return -1; \
93 } \
94
95/* The main select code.
96 */
c367dfd0 97extern "C" int
0072fdab
CF
98cygwin_select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
99 struct timeval *to)
1fd5e000
CF
100{
101 select_stuff sel;
0072fdab
CF
102 fd_set *dummy_readfds = allocfd_set (maxfds);
103 fd_set *dummy_writefds = allocfd_set (maxfds);
104 fd_set *dummy_exceptfds = allocfd_set (maxfds);
1fd5e000 105
0072fdab 106 select_printf ("%d, %p, %p, %p, %p", maxfds, readfds, writefds, exceptfds, to);
1fd5e000 107
1fd5e000 108 if (!readfds)
0072fdab 109 readfds = dummy_readfds;
1fd5e000 110 if (!writefds)
0072fdab 111 writefds = dummy_writefds;
1fd5e000 112 if (!exceptfds)
0072fdab 113 exceptfds = dummy_exceptfds;
1fd5e000 114
0072fdab 115 for (int i = 0; i < maxfds; i++)
1fd5e000
CF
116 if (!sel.test_and_set (i, readfds, writefds, exceptfds))
117 {
118 select_printf ("aborting due to test_and_set error");
119 return -1; /* Invalid fd, maybe? */
120 }
121
122 /* Convert to milliseconds or INFINITE if to == NULL */
123 DWORD ms = to ? (to->tv_sec * 1000) + (to->tv_usec / 1000) : INFINITE;
124 if (ms == 0 && to->tv_usec)
125 ms = 1; /* At least 1 ms granularity */
126
127 if (to)
128 select_printf ("to->tv_sec %d, to->tv_usec %d, ms %d", to->tv_sec, to->tv_usec, ms);
129 else
130 select_printf ("to NULL, ms %x", ms);
131
aefbf388 132 select_printf ("sel.always_ready %d", sel.always_ready);
1fd5e000 133
8d661d36
CF
134 int timeout = 0;
135 /* Allocate some fd_set structures using the number of fds as a guide. */
136 fd_set *r = allocfd_set (maxfds);
137 fd_set *w = allocfd_set (maxfds);
138 fd_set *e = allocfd_set (maxfds);
139
1fd5e000 140 /* Degenerate case. No fds to wait for. Just wait. */
aefbf388 141 if (sel.start.next == NULL)
1fd5e000 142 {
955dfa52 143 if (WaitForSingleObject (signal_arrived, ms) == WAIT_OBJECT_0)
1fd5e000
CF
144 {
145 select_printf ("signal received");
146 set_sig_errno (EINTR);
147 return -1;
148 }
8d661d36 149 timeout = 1;
1fd5e000 150 }
8d661d36 151 else if (sel.always_ready || ms == 0)
a3cfd73a 152 /* Don't bother waiting. */;
8d661d36 153 else if ((timeout = sel.wait (r, w, e, ms) < 0))
0072fdab
CF
154 return -1; /* some kind of error */
155
5835f2cf 156 sel.cleanup ();
0072fdab
CF
157 copyfd_set (readfds, r, maxfds);
158 copyfd_set (writefds, w, maxfds);
159 copyfd_set (exceptfds, e, maxfds);
8d661d36 160 return timeout ? 0 : sel.poll (readfds, writefds, exceptfds);
1fd5e000
CF
161}
162
5835f2cf
CF
163/* Call cleanup functions for all inspected fds. Gets rid of any
164 executing threads. */
165void
166select_stuff::cleanup ()
1fd5e000
CF
167{
168 select_record *s = &start;
169
170 select_printf ("calling cleanup routines");
171 while ((s = s->next))
172 if (s->cleanup)
5835f2cf
CF
173 {
174 s->cleanup (s, this);
175 s->cleanup = NULL;
176 }
177}
1fd5e000 178
5835f2cf
CF
179/* Destroy all storage associated with select stuff. */
180select_stuff::~select_stuff ()
181{
182 cleanup ();
183 select_record *s = &start;
1fd5e000
CF
184 select_record *snext = start.next;
185
186 select_printf ("deleting select records");
187 while ((s = snext))
188 {
189 snext = s->next;
190 delete s;
191 }
192}
193
194/* Add a record to the select chain */
195int
196select_stuff::test_and_set (int i, fd_set *readfds, fd_set *writefds,
197 fd_set *exceptfds)
198{
199 select_record *s = NULL;
0381fec6 200 if (UNIX_FD_ISSET (i, readfds) && (s = cygheap->fdtab.select_read (i, s)) == NULL)
1fd5e000 201 return 0; /* error */
0381fec6 202 if (UNIX_FD_ISSET (i, writefds) && (s = cygheap->fdtab.select_write (i, s)) == NULL)
1fd5e000 203 return 0; /* error */
0381fec6 204 if (UNIX_FD_ISSET (i, exceptfds) && (s = cygheap->fdtab.select_except (i, s)) == NULL)
1fd5e000
CF
205 return 0; /* error */
206 if (s == NULL)
207 return 1; /* nothing to do */
208
209 if (s->read_ready || s->write_ready || s->except_ready)
476dfb65 210 always_ready = true;
1fd5e000
CF
211
212 if (s->windows_handle || s->windows_handle || s->windows_handle)
476dfb65 213 windows_used = true;
1fd5e000
CF
214
215 s->next = start.next;
216 start.next = s;
1fd5e000
CF
217 return 1;
218}
219
1fd5e000
CF
220/* The heart of select. Waits for an fd to do something interesting. */
221int
222select_stuff::wait (fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
223 DWORD ms)
224{
225 int wait_ret;
aefbf388 226 HANDLE w4[MAXIMUM_WAIT_OBJECTS];
1fd5e000
CF
227 select_record *s = &start;
228 int m = 0;
8d661d36 229 int res = 0;
1fd5e000
CF
230
231 w4[m++] = signal_arrived; /* Always wait for the arrival of a signal. */
232 /* Loop through the select chain, starting up anything appropriate and
233 counting the number of active fds. */
234 while ((s = s->next))
235 {
fe3db6cc 236 if (m >= MAXIMUM_WAIT_OBJECTS)
b5ae313a 237 {
80a429d2 238 set_sig_errno (EINVAL);
b5ae313a
CF
239 return -1;
240 }
1fd5e000
CF
241 if (!s->startup (s, this))
242 {
243 __seterrno ();
244 return -1;
245 }
246 if (s->h == NULL)
247 continue;
248 for (int i = 1; i < m; i++)
249 if (w4[i] == s->h)
250 goto next_while;
251 w4[m++] = s->h;
252 next_while:
253 continue;
254 }
255
1fd5e000
CF
256 DWORD start_time = GetTickCount (); /* Record the current time for later use. */
257
0072fdab 258 debug_printf ("m %d, ms %u", m, ms);
1fd5e000
CF
259 for (;;)
260 {
261 if (!windows_used)
262 wait_ret = WaitForMultipleObjects (m, w4, FALSE, ms);
263 else
264 wait_ret = MsgWaitForMultipleObjects (m, w4, FALSE, ms, QS_ALLINPUT);
265
266 switch (wait_ret)
267 {
268 case WAIT_OBJECT_0:
269 select_printf ("signal received");
270 set_sig_errno (EINTR);
271 return -1;
272 case WAIT_FAILED:
273 select_printf ("WaitForMultipleObjects failed");
274 __seterrno ();
275 return -1;
276 case WAIT_TIMEOUT:
277 select_printf ("timed out");
8d661d36 278 res = 1;
1fd5e000
CF
279 goto out;
280 }
281
282 select_printf ("woke up. wait_ret %d. verifying", wait_ret);
283 s = &start;
2e008fb9 284 bool gotone = false;
915d1824 285 /* Some types of object (e.g., consoles) wake up on "inappropriate" events
9c510edc 286 like mouse movements. The verify function will detect these situations.
915d1824
CF
287 If it returns false, then this wakeup was a false alarm and we should go
288 back to waiting. */
1fd5e000
CF
289 while ((s = s->next))
290 if (s->saw_error)
291 return -1; /* Somebody detected an error */
292 else if ((((wait_ret >= m && s->windows_handle) || s->h == w4[wait_ret])) &&
0072fdab 293 s->verify (s, readfds, writefds, exceptfds))
476dfb65 294 gotone = true;
1fd5e000
CF
295
296 select_printf ("gotone %d", gotone);
297 if (gotone)
298 goto out;
299
300 if (ms == INFINITE)
301 {
302 select_printf ("looping");
303 continue;
304 }
305 select_printf ("recalculating ms");
306
307 DWORD now = GetTickCount ();
308 if (now > (start_time + ms))
309 {
310 select_printf ("timed out after verification");
311 goto out;
312 }
313 ms -= (now - start_time);
314 start_time = now;
315 select_printf ("ms now %u", ms);
316 }
317
318out:
8d661d36
CF
319 select_printf ("returning %d", res);
320 return res;
1fd5e000
CF
321}
322
323static int
324set_bits (select_record *me, fd_set *readfds, fd_set *writefds,
711ded6d 325 fd_set *exceptfds)
1fd5e000
CF
326{
327 int ready = 0;
328 select_printf ("me %p, testing fd %d (%s)", me, me->fd, me->fh->get_name ());
329 if (me->read_selected && me->read_ready)
330 {
331 UNIX_FD_SET (me->fd, readfds);
332 ready++;
333 }
334 if (me->write_selected && me->write_ready)
335 {
336 UNIX_FD_SET (me->fd, writefds);
7ac61736 337 if (me->except_on_write && me->fh->is_socket ())
56551a9b 338 ((fhandler_socket *) me->fh)->connect_state (connected);
1fd5e000
CF
339 ready++;
340 }
6bb769ef 341 if ((me->except_selected || me->except_on_write) && me->except_ready)
1fd5e000 342 {
6bb769ef 343 if (me->except_on_write) /* Only on sockets */
6cae97d5 344 {
6bb769ef 345 UNIX_FD_SET (me->fd, writefds);
7ac61736 346 if (me->fh->is_socket ())
56551a9b 347 ((fhandler_socket *) me->fh)->connect_state (connected);
6cae97d5 348 }
6bb769ef
CV
349 if (me->except_selected)
350 UNIX_FD_SET (me->fd, exceptfds);
1fd5e000
CF
351 ready++;
352 }
353 select_printf ("ready %d", ready);
354 return ready;
355}
356
476dfb65
CF
357/* Poll every fd in the select chain. Set appropriate fd in mask. */
358int
359select_stuff::poll (fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
360{
361 int n = 0;
362 select_record *s = &start;
363 while ((s = s->next))
364 n += (!s->peek || s->peek (s, true)) ?
365 set_bits (s, readfds, writefds, exceptfds) : 0;
366 select_printf ("returning %d", n);
367 return n;
368}
369
1fd5e000 370static int
9cec3d45 371verify_true (select_record *, fd_set *, fd_set *, fd_set *)
1fd5e000
CF
372{
373 return 1;
374}
375
376static int
377verify_ok (select_record *me, fd_set *readfds, fd_set *writefds,
378 fd_set *exceptfds)
379{
380 return set_bits (me, readfds, writefds, exceptfds);
381}
382
383static int
9cec3d45 384no_startup (select_record *, select_stuff *)
1fd5e000
CF
385{
386 return 1;
387}
388
389static int
390no_verify (select_record *, fd_set *, fd_set *, fd_set *)
391{
392 return 0;
393}
394
395static int
476dfb65 396peek_pipe (select_record *s, bool from_select)
1fd5e000
CF
397{
398 int n = 0;
399 int gotone = 0;
400 fhandler_base *fh = s->fh;
401
402 HANDLE h;
403 set_handle_or_return_if_not_open (h, s);
404
915d1824
CF
405 /* pipes require a guard mutex to guard against the situation where multiple
406 readers are attempting to read from the same pipe. In this scenario, it
407 is possible for PeekNamedPipe to report available data to two readers but
408 only one will actually get the data. This will result in the other reader
409 entering fhandler_base::raw_read and blocking indefinitely in an interruptible
410 state. This causes things like "make -j2" to hang. So, for the non-select case
411 we use the pipe mutex, if it is available. */
476dfb65 412 HANDLE guard_mutex = from_select ? NULL : fh->get_guard ();
915d1824 413
1fd5e000
CF
414 /* Don't perform complicated tests if we don't need to. */
415 if (!s->read_selected && !s->except_selected)
416 goto out;
417
3f0b4935 418 if (s->read_selected)
1fd5e000 419 {
41010c6a
CF
420 if (s->read_ready)
421 {
6644c628 422 select_printf ("%s, already ready for read", fh->get_name ());
41010c6a
CF
423 gotone = 1;
424 goto out;
425 }
1fd5e000 426
c5d03f3d 427 switch (fh->get_device ())
3f0b4935 428 {
c5d03f3d
CF
429 case FH_PTYM:
430 case FH_TTYM:
1d380f59 431 if (((fhandler_pty_master *) fh)->need_nl)
c5d03f3d 432 {
915d1824 433 gotone = s->read_ready = true;
c5d03f3d
CF
434 goto out;
435 }
436 break;
437 default:
476dfb65 438 if (fh->get_readahead_valid ())
c5d03f3d
CF
439 {
440 select_printf ("readahead");
915d1824 441 gotone = s->read_ready = true;
c5d03f3d
CF
442 goto out;
443 }
3f0b4935 444 }
35f879a6
CF
445
446 if (fh->bg_check (SIGTTIN) <= bg_eof)
447 {
915d1824 448 gotone = s->read_ready = true;
35f879a6
CF
449 goto out;
450 }
1fd5e000
CF
451 }
452
5e733918 453 if (fh->get_device () == FH_PIPEW)
6644c628
CF
454 select_printf ("%s, select for read/except on write end of pipe",
455 fh->get_name ());
32638384
CF
456 else if (!PeekNamedPipe (h, NULL, 0, NULL, (DWORD *) &n, NULL))
457 {
458 select_printf ("%s, PeekNamedPipe failed, %E", fh->get_name ());
459 n = -1;
460 }
c4157069 461 else if (!n || !guard_mutex)
907dc7d0 462 /* no guard mutex or nothing to read from the pipe. */;
c4157069
CF
463 else if (WaitForSingleObject (guard_mutex, 0) != WAIT_OBJECT_0)
464 {
465 select_printf ("%s, couldn't get mutex %p, %E", fh->get_name (),
466 guard_mutex);
467 n = 0;
468 }
469 else
5e733918 470 {
243a041b 471 /* Now that we have the mutex, make sure that no one else has snuck
c4157069 472 in and grabbed the data that we originally saw. */
243a041b
CF
473 if (!PeekNamedPipe (h, NULL, 0, NULL, (DWORD *) &n, NULL))
474 {
475 select_printf ("%s, PeekNamedPipe failed, %E", fh->get_name ());
476 n = -1;
477 }
478 if (n <= 0)
479 ReleaseMutex (guard_mutex); /* Oops. We lost the race. */
5e733918 480 }
1fd5e000
CF
481
482 if (n < 0)
483 {
915d1824 484 fh->set_eof (); /* Flag that other end of pipe is gone */
1fd5e000
CF
485 select_printf ("%s, n %d", fh->get_name (), n);
486 if (s->except_selected)
476dfb65 487 gotone += s->except_ready = true;
1fd5e000 488 if (s->read_selected)
476dfb65 489 gotone += s->read_ready = true;
1fd5e000
CF
490 }
491 if (n > 0 && s->read_selected)
492 {
6644c628 493 select_printf ("%s, ready for read: avail %d", fh->get_name (), n);
476dfb65 494 gotone += s->read_ready = true;
1fd5e000
CF
495 }
496 if (!gotone && s->fh->hit_eof ())
497 {
498 select_printf ("%s, saw EOF", fh->get_name ());
499 if (s->except_selected)
6644c628 500 gotone += s->except_ready = true;
1fd5e000 501 if (s->read_selected)
476dfb65 502 gotone += s->read_ready = true;
1fd5e000
CF
503 }
504
505out:
6644c628
CF
506 if (s->write_selected)
507 {
508 if (s->write_ready)
d584454c
CF
509 {
510 select_printf ("%s, already ready for write", fh->get_name ());
511 gotone++;
512 }
6644c628
CF
513 /* Do we need to do anything about SIGTTOU here? */
514 else if (fh->get_device () == FH_PIPER)
515 select_printf ("%s, select for write on read end of pipe",
516 fh->get_name ());
517 else
d584454c
CF
518 {
519 /* We don't worry about the guard mutex, because that only applies
520 when from_select is false, and peek_pipe is never called that
521 way for writes. */
522
523 IO_STATUS_BLOCK iosb = {0};
524 FILE_PIPE_LOCAL_INFORMATION fpli = {0};
525
526 if (NtQueryInformationFile (h,
527 &iosb,
528 &fpli,
529 sizeof (fpli),
530 FilePipeLocalInformation))
531 {
532 /* If NtQueryInformationFile fails, optimistically assume the
533 pipe is writable. This could happen on Win9x, because
534 NtQueryInformationFile is not available, or if we somehow
535 inherit a pipe that doesn't permit FILE_READ_ATTRIBUTES
536 access on the write end. */
537 select_printf ("%s, NtQueryInformationFile failed",
538 fh->get_name ());
539 gotone += s->write_ready = true;
540 }
541 /* Ensure that enough space is available for atomic writes,
542 as required by POSIX. Subsequent writes with size > PIPE_BUF
543 can still block, but most (all?) UNIX variants seem to work
544 this way (e.g., BSD, Linux, Solaris). */
545 else if (fpli.WriteQuotaAvailable >= PIPE_BUF)
546 {
547 select_printf ("%s, ready for write: size %lu, avail %lu",
548 fh->get_name (),
549 fpli.OutboundQuota,
550 fpli.WriteQuotaAvailable);
551 gotone += s->write_ready = true;
552 }
553 /* If we somehow inherit a tiny pipe (size < PIPE_BUF), then consider
554 the pipe writable only if it is completely empty, to minimize the
555 probability that a subsequent write will block. */
556 else if (fpli.OutboundQuota < PIPE_BUF &&
557 fpli.WriteQuotaAvailable == fpli.OutboundQuota)
558 {
559 select_printf ("%s, tiny pipe: size %lu, avail %lu",
560 fh->get_name (),
561 fpli.OutboundQuota,
562 fpli.WriteQuotaAvailable);
563 gotone += s->write_ready = true;
564 }
565 }
6644c628
CF
566 }
567
568 return gotone;
1fd5e000
CF
569}
570
1fd5e000
CF
571static int start_thread_pipe (select_record *me, select_stuff *stuff);
572
573struct pipeinf
574 {
b6bd7037 575 cygthread *thread;
2e008fb9 576 bool stop_thread_pipe;
1fd5e000
CF
577 select_record *start;
578 };
579
580static DWORD WINAPI
581thread_pipe (void *arg)
582{
1d380f59 583 pipeinf *pi = (pipeinf *) arg;
2e008fb9 584 bool gotone = false;
1fd5e000
CF
585
586 for (;;)
587 {
588 select_record *s = pi->start;
589 while ((s = s->next))
590 if (s->startup == start_thread_pipe)
591 {
476dfb65
CF
592 if (peek_pipe (s, true))
593 gotone = true;
1fd5e000
CF
594 if (pi->stop_thread_pipe)
595 {
596 select_printf ("stopping");
597 goto out;
598 }
599 }
2a6a56c2
CF
600 /* Paranoid check */
601 if (pi->stop_thread_pipe)
602 {
603 select_printf ("stopping from outer loop");
604 break;
605 }
1fd5e000
CF
606 if (gotone)
607 break;
608 Sleep (10);
609 }
610out:
611 return 0;
612}
613
614static int
615start_thread_pipe (select_record *me, select_stuff *stuff)
616{
7ac61736 617 if (stuff->device_specific_pipe)
1fd5e000 618 {
7ac61736 619 me->h = *((pipeinf *) stuff->device_specific_pipe)->thread;
1fd5e000
CF
620 return 1;
621 }
622 pipeinf *pi = new pipeinf;
623 pi->start = &stuff->start;
2e008fb9 624 pi->stop_thread_pipe = false;
1d380f59 625 pi->thread = new cygthread (thread_pipe, (LPVOID) pi, "select_pipe");
b6bd7037 626 me->h = *pi->thread;
1fd5e000
CF
627 if (!me->h)
628 return 0;
7ac61736 629 stuff->device_specific_pipe = (void *) pi;
1fd5e000
CF
630 return 1;
631}
632
633static void
9cec3d45 634pipe_cleanup (select_record *, select_stuff *stuff)
1fd5e000 635{
7ac61736 636 pipeinf *pi = (pipeinf *) stuff->device_specific_pipe;
1fd5e000
CF
637 if (pi && pi->thread)
638 {
476dfb65 639 pi->stop_thread_pipe = true;
b6bd7037 640 pi->thread->detach ();
1fd5e000 641 delete pi;
7ac61736 642 stuff->device_specific_pipe = NULL;
1fd5e000
CF
643 }
644}
645
1d380f59
CF
646int
647fhandler_pipe::ready_for_read (int fd, DWORD howlong)
648{
0eaf24fe
CF
649 int res;
650 if (howlong)
651 res = true;
652 else
653 res = fhandler_base::ready_for_read (fd, howlong);
1d380f59 654
0eaf24fe
CF
655 if (res)
656 get_guard ();
657 return res;
1d380f59
CF
658}
659
1fd5e000
CF
660select_record *
661fhandler_pipe::select_read (select_record *s)
662{
663 if (!s)
664 s = new select_record;
665 s->startup = start_thread_pipe;
1229d4f4 666 s->peek = peek_pipe;
1fd5e000 667 s->verify = verify_ok;
6644c628 668 s->cleanup = pipe_cleanup;
476dfb65
CF
669 s->read_selected = true;
670 s->read_ready = false;
1fd5e000
CF
671 return s;
672}
673
674select_record *
675fhandler_pipe::select_write (select_record *s)
676{
677 if (!s)
6644c628
CF
678 s = new select_record;
679 s->startup = start_thread_pipe;
476dfb65 680 s->peek = peek_pipe;
6644c628
CF
681 s->verify = verify_ok;
682 s->cleanup = pipe_cleanup;
476dfb65 683 s->write_selected = true;
6644c628 684 s->write_ready = false;
1fd5e000
CF
685 return s;
686}
687
688select_record *
689fhandler_pipe::select_except (select_record *s)
690{
691 if (!s)
6644c628 692 s = new select_record;
1fd5e000 693 s->startup = start_thread_pipe;
476dfb65 694 s->peek = peek_pipe;
1fd5e000
CF
695 s->verify = verify_ok;
696 s->cleanup = pipe_cleanup;
476dfb65
CF
697 s->except_selected = true;
698 s->except_ready = false;
1fd5e000
CF
699 return s;
700}
701
702static int
476dfb65 703peek_console (select_record *me, bool)
1fd5e000 704{
a9867e1b 705 extern const char * get_nonascii_key (INPUT_RECORD& input_rec, char *);
1d380f59 706 fhandler_console *fh = (fhandler_console *) me->fh;
1fd5e000
CF
707
708 if (!me->read_selected)
709 return me->write_ready;
710
476dfb65 711 if (fh->get_readahead_valid ())
1fd5e000
CF
712 {
713 select_printf ("readahead");
915d1824 714 return me->read_ready = true;
1fd5e000
CF
715 }
716
41010c6a
CF
717 if (me->read_ready)
718 {
719 select_printf ("already ready");
720 return 1;
721 }
722
1fd5e000
CF
723 INPUT_RECORD irec;
724 DWORD events_read;
725 HANDLE h;
a9867e1b 726 char tmpbuf[17];
1fd5e000
CF
727 set_handle_or_return_if_not_open (h, me);
728
729 for (;;)
a7cde2b9 730 if (fh->bg_check (SIGTTIN) <= bg_eof)
915d1824 731 return me->read_ready = true;
1fd5e000
CF
732 else if (!PeekConsoleInput (h, &irec, 1, &events_read) || !events_read)
733 break;
734 else
735 {
c060edba 736 if (irec.EventType == KEY_EVENT)
d80999a1 737 {
c060edba
CF
738 if (irec.Event.KeyEvent.bKeyDown
739 && (irec.Event.KeyEvent.uChar.AsciiChar
740 || get_nonascii_key (irec, tmpbuf)))
915d1824 741 return me->read_ready = true;
d80999a1 742 }
c060edba
CF
743 else
744 {
745 fh->send_winch_maybe ();
746 if (irec.EventType == MOUSE_EVENT
747 && fh->mouse_aware ()
748 && (irec.Event.MouseEvent.dwEventFlags == 0
749 || irec.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK))
750 return me->read_ready = true;
751 }
1fd5e000
CF
752
753 /* Read and discard the event */
754 ReadConsoleInput (h, &irec, 1, &events_read);
755 }
756
757 return me->write_ready;
758}
9c510edc 759
763f09b9
CF
760static int
761verify_console (select_record *me, fd_set *rfds, fd_set *wfds,
762 fd_set *efds)
763{
764 return peek_console (me, true);
765}
766
1fd5e000 767
1fd5e000
CF
768select_record *
769fhandler_console::select_read (select_record *s)
770{
771 if (!s)
772 {
773 s = new select_record;
774 s->startup = no_startup;
763f09b9 775 s->verify = verify_console;
e5dd8811 776 set_cursor_maybe ();
1fd5e000
CF
777 }
778
1229d4f4 779 s->peek = peek_console;
1fd5e000 780 s->h = get_handle ();
476dfb65
CF
781 s->read_selected = true;
782 s->read_ready = false;
1fd5e000
CF
783 return s;
784}
785
786select_record *
787fhandler_console::select_write (select_record *s)
788{
789 if (!s)
790 {
791 s = new select_record;
792 s->startup = no_startup;
1fd5e000 793 s->verify = no_verify;
e5dd8811 794 set_cursor_maybe ();
1fd5e000
CF
795 }
796
476dfb65
CF
797 s->peek = peek_console;
798 s->write_selected = true;
799 s->write_ready = true;
1fd5e000
CF
800 return s;
801}
802
803select_record *
804fhandler_console::select_except (select_record *s)
805{
806 if (!s)
807 {
808 s = new select_record;
809 s->startup = no_startup;
1fd5e000 810 s->verify = no_verify;
e5dd8811 811 set_cursor_maybe ();
1fd5e000
CF
812 }
813
476dfb65
CF
814 s->peek = peek_console;
815 s->except_selected = true;
816 s->except_ready = false;
1fd5e000
CF
817 return s;
818}
819
1fd5e000
CF
820select_record *
821fhandler_tty_common::select_read (select_record *s)
822{
1d380f59 823 return ((fhandler_pipe *) this)->fhandler_pipe::select_read (s);
1fd5e000
CF
824}
825
826select_record *
827fhandler_tty_common::select_write (select_record *s)
828{
1d380f59 829 return ((fhandler_pipe *) this)->fhandler_pipe::select_write (s);
1fd5e000
CF
830}
831
832select_record *
833fhandler_tty_common::select_except (select_record *s)
834{
1d380f59 835 return ((fhandler_pipe *) this)->fhandler_pipe::select_except (s);
1fd5e000
CF
836}
837
5e8e21d9
ED
838static int
839verify_tty_slave (select_record *me, fd_set *readfds, fd_set *writefds,
840 fd_set *exceptfds)
841{
842 if (WaitForSingleObject (me->h, 0) == WAIT_OBJECT_0)
915d1824 843 me->read_ready = true;
5e8e21d9
ED
844 return set_bits (me, readfds, writefds, exceptfds);
845}
846
847select_record *
848fhandler_tty_slave::select_read (select_record *s)
849{
850 if (!s)
851 s = new select_record;
852 s->h = input_available_event;
853 s->startup = no_startup;
1229d4f4 854 s->peek = peek_pipe;
5e8e21d9 855 s->verify = verify_tty_slave;
476dfb65
CF
856 s->read_selected = true;
857 s->read_ready = false;
5e8e21d9
ED
858 s->cleanup = NULL;
859 return s;
860}
861
1fd5e000
CF
862select_record *
863fhandler_dev_null::select_read (select_record *s)
864{
865 if (!s)
866 {
867 s = new select_record;
868 s->startup = no_startup;
1fd5e000
CF
869 s->verify = no_verify;
870 }
871 s->h = get_handle ();
476dfb65
CF
872 s->read_selected = true;
873 s->read_ready = true;
1fd5e000
CF
874 return s;
875}
876
877select_record *
878fhandler_dev_null::select_write (select_record *s)
879{
880 if (!s)
881 {
882 s = new select_record;
883 s->startup = no_startup;
1fd5e000
CF
884 s->verify = no_verify;
885 }
886 s->h = get_handle ();
476dfb65
CF
887 s->write_selected = true;
888 s->write_ready = true;
1fd5e000
CF
889 return s;
890}
891
892select_record *
893fhandler_dev_null::select_except (select_record *s)
894{
895 if (!s)
896 {
897 s = new select_record;
898 s->startup = no_startup;
1fd5e000
CF
899 s->verify = no_verify;
900 }
901 s->h = get_handle ();
476dfb65
CF
902 s->except_selected = true;
903 s->except_ready = true;
1fd5e000
CF
904 return s;
905}
906
907static int start_thread_serial (select_record *me, select_stuff *stuff);
908
909struct serialinf
910 {
b6bd7037 911 cygthread *thread;
2e008fb9 912 bool stop_thread_serial;
1fd5e000
CF
913 select_record *start;
914 };
915
916static int
476dfb65 917peek_serial (select_record *s, bool)
1fd5e000 918{
1fd5e000
CF
919 COMSTAT st;
920
1d380f59 921 fhandler_serial *fh = (fhandler_serial *) s->fh;
1fd5e000
CF
922
923 if (fh->get_readahead_valid () || fh->overlapped_armed < 0)
915d1824 924 return s->read_ready = true;
1fd5e000
CF
925
926 select_printf ("fh->overlapped_armed %d", fh->overlapped_armed);
927
928 HANDLE h;
929 set_handle_or_return_if_not_open (h, s);
930 int ready = 0;
41010c6a
CF
931
932 if (s->read_selected && s->read_ready || (s->write_selected && s->write_ready))
933 {
934 select_printf ("already ready");
935 ready = 1;
936 goto out;
937 }
938
1fd5e000
CF
939 (void) SetCommMask (h, EV_RXCHAR);
940
941 if (!fh->overlapped_armed)
942 {
1fd5e000
CF
943 COMSTAT st;
944
945 ResetEvent (fh->io_status.hEvent);
946
40139114 947 if (!ClearCommError (h, &fh->ev, &st))
1fd5e000
CF
948 {
949 debug_printf ("ClearCommError");
950 goto err;
951 }
952 else if (st.cbInQue)
915d1824 953 return s->read_ready = true;
40139114 954 else if (WaitCommEvent (h, &fh->ev, &fh->io_status))
915d1824 955 return s->read_ready = true;
1fd5e000
CF
956 else if (GetLastError () == ERROR_IO_PENDING)
957 fh->overlapped_armed = 1;
958 else
959 {
960 debug_printf ("WaitCommEvent");
961 goto err;
962 }
963 }
964
965 HANDLE w4[2];
966 DWORD to;
967
968 w4[0] = fh->io_status.hEvent;
969 w4[1] = signal_arrived;
970 to = 10;
971
972 switch (WaitForMultipleObjects (2, w4, FALSE, to))
973 {
974 case WAIT_OBJECT_0:
40139114 975 if (!ClearCommError (h, &fh->ev, &st))
b0e82b74
CF
976 {
977 debug_printf ("ClearCommError");
978 goto err;
979 }
1fd5e000
CF
980 else if (!st.cbInQue)
981 Sleep (to);
982 else
983 {
915d1824 984 return s->read_ready = true;
1fd5e000
CF
985 select_printf ("got something");
986 }
1fd5e000
CF
987 break;
988 case WAIT_OBJECT_0 + 1:
1fd5e000
CF
989 select_printf ("interrupt");
990 set_sig_errno (EINTR);
991 ready = -1;
992 break;
993 case WAIT_TIMEOUT:
1fd5e000
CF
994 break;
995 default:
1fd5e000
CF
996 debug_printf ("WaitForMultipleObjects");
997 goto err;
998 }
999
41010c6a 1000out:
1fd5e000
CF
1001 return ready;
1002
1003err:
1004 if (GetLastError () == ERROR_OPERATION_ABORTED)
1005 {
1006 select_printf ("operation aborted");
1007 return ready;
1008 }
1009
1010 __seterrno ();
476dfb65 1011 s->saw_error = true;
1fd5e000
CF
1012 select_printf ("error %E");
1013 return -1;
1014}
1015
1016static DWORD WINAPI
1017thread_serial (void *arg)
1018{
1d380f59 1019 serialinf *si = (serialinf *) arg;
2e008fb9 1020 bool gotone = false;
1fd5e000
CF
1021
1022 for (;;)
1023 {
1024 select_record *s = si->start;
1025 while ((s = s->next))
1026 if (s->startup == start_thread_serial)
1027 {
476dfb65
CF
1028 if (peek_serial (s, true))
1029 gotone = true;
1fd5e000
CF
1030 }
1031 if (si->stop_thread_serial)
1032 {
1033 select_printf ("stopping");
1034 break;
1035 }
1036 if (gotone)
1037 break;
1038 }
1039
1040 select_printf ("exiting");
1041 return 0;
1042}
1043
1044static int
1045start_thread_serial (select_record *me, select_stuff *stuff)
1046{
7ac61736 1047 if (stuff->device_specific_serial)
1fd5e000 1048 {
7ac61736 1049 me->h = *((serialinf *) stuff->device_specific_serial)->thread;
1fd5e000
CF
1050 return 1;
1051 }
1052 serialinf *si = new serialinf;
1053 si->start = &stuff->start;
2e008fb9 1054 si->stop_thread_serial = false;
1d380f59 1055 si->thread = new cygthread (thread_serial, (LPVOID) si, "select_serial");
b6bd7037 1056 me->h = *si->thread;
7ac61736 1057 stuff->device_specific_serial = (void *) si;
1fd5e000
CF
1058 return 1;
1059}
1060
1061static void
9cec3d45 1062serial_cleanup (select_record *, select_stuff *stuff)
1fd5e000 1063{
7ac61736 1064 serialinf *si = (serialinf *) stuff->device_specific_serial;
1fd5e000
CF
1065 if (si && si->thread)
1066 {
476dfb65 1067 si->stop_thread_serial = true;
b6bd7037 1068 si->thread->detach ();
1fd5e000 1069 delete si;
7ac61736 1070 stuff->device_specific_serial = NULL;
1fd5e000
CF
1071 }
1072}
1073
1fd5e000
CF
1074select_record *
1075fhandler_serial::select_read (select_record *s)
1076{
1077 if (!s)
1078 {
1079 s = new select_record;
1080 s->startup = start_thread_serial;
1fd5e000
CF
1081 s->verify = verify_ok;
1082 s->cleanup = serial_cleanup;
1083 }
1229d4f4 1084 s->peek = peek_serial;
476dfb65
CF
1085 s->read_selected = true;
1086 s->read_ready = false;
1fd5e000
CF
1087 return s;
1088}
1089
1090select_record *
1091fhandler_serial::select_write (select_record *s)
1092{
1093 if (!s)
1094 {
1095 s = new select_record;
1096 s->startup = no_startup;
1fd5e000
CF
1097 s->verify = verify_ok;
1098 }
476dfb65 1099 s->peek = peek_serial;
1fd5e000 1100 s->h = get_handle ();
476dfb65
CF
1101 s->write_selected = true;
1102 s->write_ready = true;
1fd5e000
CF
1103 return s;
1104}
1105
1106select_record *
1107fhandler_serial::select_except (select_record *s)
1108{
1109 if (!s)
1110 {
1111 s = new select_record;
1112 s->startup = no_startup;
1fd5e000
CF
1113 s->verify = verify_ok;
1114 }
1115 s->h = NULL;
476dfb65
CF
1116 s->peek = peek_serial;
1117 s->except_selected = false; // Can't do this
1118 s->except_ready = false;
1fd5e000
CF
1119 return s;
1120}
1121
1122int
476dfb65 1123fhandler_base::ready_for_read (int fd, DWORD howlong)
1fd5e000 1124{
1229d4f4
CF
1125 int avail = 0;
1126 select_record me (this);
1127 me.fd = fd;
1128 while (!avail)
1129 {
1130 (void) select_read (&me);
476dfb65 1131 avail = me.read_ready ?: me.peek (&me, false);
1229d4f4
CF
1132
1133 if (fd >= 0 && cygheap->fdtab.not_open (fd))
1134 {
80a429d2 1135 set_sig_errno (EBADF);
1229d4f4
CF
1136 avail = 0;
1137 break;
1138 }
1139
1140 if (howlong != INFINITE)
1141 {
1142 if (!avail)
80a429d2 1143 set_sig_errno (EAGAIN);
1229d4f4
CF
1144 break;
1145 }
1146
1147 if (WaitForSingleObject (signal_arrived, avail ? 0 : 10) == WAIT_OBJECT_0)
1148 {
9a4d574b 1149 debug_printf ("interrupted");
80a429d2 1150 set_sig_errno (EINTR);
1229d4f4
CF
1151 avail = 0;
1152 break;
1153 }
1154 }
1155
53f00290
CF
1156 if (get_guard () && !avail && me.read_ready)
1157 ReleaseMutex (get_guard ());
1158
1229d4f4
CF
1159 select_printf ("read_ready %d, avail %d", me.read_ready, avail);
1160 return avail;
1fd5e000
CF
1161}
1162
1163select_record *
1164fhandler_base::select_read (select_record *s)
1165{
1166 if (!s)
1167 {
1168 s = new select_record;
1169 s->startup = no_startup;
1fd5e000
CF
1170 s->verify = verify_ok;
1171 }
1172 s->h = get_handle ();
476dfb65
CF
1173 s->read_selected = true;
1174 s->read_ready = true;
1fd5e000
CF
1175 return s;
1176}
1177
1178select_record *
1179fhandler_base::select_write (select_record *s)
1180{
1181 if (!s)
1182 {
1183 s = new select_record;
1184 s->startup = no_startup;
1fd5e000
CF
1185 s->verify = verify_ok;
1186 }
1187 s->h = get_handle ();
476dfb65
CF
1188 s->write_selected = true;
1189 s->write_ready = true;
1fd5e000
CF
1190 return s;
1191}
1192
1193select_record *
1194fhandler_base::select_except (select_record *s)
1195{
1196 if (!s)
1197 {
1198 s = new select_record;
1199 s->startup = no_startup;
1fd5e000
CF
1200 s->verify = verify_ok;
1201 }
1202 s->h = NULL;
476dfb65
CF
1203 s->except_selected = true;
1204 s->except_ready = false;
1fd5e000
CF
1205 return s;
1206}
1207
1208struct socketinf
1209 {
b6bd7037 1210 cygthread *thread;
1fd5e000
CF
1211 winsock_fd_set readfds, writefds, exceptfds;
1212 SOCKET exitsock;
1fd5e000
CF
1213 select_record *start;
1214 };
1215
1216static int
476dfb65 1217peek_socket (select_record *me, bool)
1fd5e000
CF
1218{
1219 winsock_fd_set ws_readfds, ws_writefds, ws_exceptfds;
01cf5d0f 1220 struct timeval tv = {0, 0};
1fd5e000
CF
1221 WINSOCK_FD_ZERO (&ws_readfds);
1222 WINSOCK_FD_ZERO (&ws_writefds);
1223 WINSOCK_FD_ZERO (&ws_exceptfds);
1fd5e000
CF
1224
1225 HANDLE h;
1226 set_handle_or_return_if_not_open (h, me);
1227 select_printf ("considering handle %p", h);
1228
d5591d9d 1229 if (me->read_selected && !me->read_ready)
1fd5e000
CF
1230 {
1231 select_printf ("adding read fd_set %s, fd %d", me->fh->get_name (),
1232 me->fd);
1233 WINSOCK_FD_SET (h, &ws_readfds);
1234 }
d5591d9d 1235 if (me->write_selected && !me->write_ready)
1fd5e000
CF
1236 {
1237 select_printf ("adding write fd_set %s, fd %d", me->fh->get_name (),
1238 me->fd);
1239 WINSOCK_FD_SET (h, &ws_writefds);
1240 }
6bb769ef 1241 if ((me->except_selected || me->except_on_write) && !me->except_ready)
1fd5e000
CF
1242 {
1243 select_printf ("adding except fd_set %s, fd %d", me->fh->get_name (),
1244 me->fd);
1245 WINSOCK_FD_SET (h, &ws_exceptfds);
1246 }
d5591d9d
CV
1247 int r;
1248 if ((me->read_selected && !me->read_ready)
1249 || (me->write_selected && !me->write_ready)
6bb769ef 1250 || ((me->except_selected || me->except_on_write) && !me->except_ready))
1fd5e000 1251 {
d5591d9d
CV
1252 r = WINSOCK_SELECT (0, &ws_readfds, &ws_writefds, &ws_exceptfds, &tv);
1253 select_printf ("WINSOCK_SELECT returned %d", r);
1254 if (r == -1)
1255 {
1256 select_printf ("error %d", WSAGetLastError ());
1257 set_winsock_errno ();
1258 return 0;
1259 }
1260 if (WINSOCK_FD_ISSET (h, &ws_readfds) || (me->read_selected && me->read_ready))
1261 me->read_ready = true;
1262 if (WINSOCK_FD_ISSET (h, &ws_writefds) || (me->write_selected && me->write_ready))
1263 me->write_ready = true;
6bb769ef 1264 if (WINSOCK_FD_ISSET (h, &ws_exceptfds) || ((me->except_selected || me->except_on_write) && me->except_ready))
d5591d9d 1265 me->except_ready = true;
1fd5e000 1266 }
fe00cca9 1267 return me->read_ready || me->write_ready || me->except_ready;
1fd5e000
CF
1268}
1269
1fd5e000
CF
1270static int start_thread_socket (select_record *, select_stuff *);
1271
1272static DWORD WINAPI
1273thread_socket (void *arg)
1274{
1d380f59 1275 socketinf *si = (socketinf *) arg;
1fd5e000
CF
1276
1277 select_printf ("stuff_start %p", &si->start);
1278 int r = WINSOCK_SELECT (0, &si->readfds, &si->writefds, &si->exceptfds, NULL);
1279 select_printf ("Win32 select returned %d", r);
1280 if (r == -1)
1281 select_printf ("error %d", WSAGetLastError ());
1282 select_record *s = si->start;
1283 while ((s = s->next))
1284 if (s->startup == start_thread_socket)
1285 {
1286 HANDLE h = s->fh->get_handle ();
1287 select_printf ("s %p, testing fd %d (%s)", s, s->fd, s->fh->get_name ());
1288 if (WINSOCK_FD_ISSET (h, &si->readfds))
1289 {
1290 select_printf ("read_ready");
476dfb65 1291 s->read_ready = true;
1fd5e000
CF
1292 }
1293 if (WINSOCK_FD_ISSET (h, &si->writefds))
1294 {
1295 select_printf ("write_ready");
476dfb65 1296 s->write_ready = true;
1fd5e000
CF
1297 }
1298 if (WINSOCK_FD_ISSET (h, &si->exceptfds))
1299 {
1300 select_printf ("except_ready");
476dfb65 1301 s->except_ready = true;
1fd5e000
CF
1302 }
1303 }
1304
1305 if (WINSOCK_FD_ISSET (si->exitsock, &si->readfds))
1306 select_printf ("saw exitsock read");
1fd5e000
CF
1307 return 0;
1308}
1309
1fd5e000
CF
1310static int
1311start_thread_socket (select_record *me, select_stuff *stuff)
1312{
1313 socketinf *si;
1314
7ac61736 1315 if ((si = (socketinf *) stuff->device_specific_socket))
1fd5e000 1316 {
b6bd7037 1317 me->h = *si->thread;
1fd5e000
CF
1318 return 1;
1319 }
1320
1321 si = new socketinf;
1322 WINSOCK_FD_ZERO (&si->readfds);
1323 WINSOCK_FD_ZERO (&si->writefds);
1324 WINSOCK_FD_ZERO (&si->exceptfds);
1325 select_record *s = &stuff->start;
1326 while ((s = s->next))
1327 if (s->startup == start_thread_socket)
1328 {
1329 HANDLE h = s->fh->get_handle ();
1330 select_printf ("Handle %p", h);
d5591d9d 1331 if (s->read_selected && !s->read_ready)
1fd5e000
CF
1332 {
1333 WINSOCK_FD_SET (h, &si->readfds);
1334 select_printf ("Added to readfds");
1335 }
d5591d9d 1336 if (s->write_selected && !s->write_ready)
1fd5e000
CF
1337 {
1338 WINSOCK_FD_SET (h, &si->writefds);
1339 select_printf ("Added to writefds");
1340 }
6bb769ef 1341 if ((s->except_selected || s->except_on_write) && !s->except_ready)
1fd5e000
CF
1342 {
1343 WINSOCK_FD_SET (h, &si->exceptfds);
1344 select_printf ("Added to exceptfds");
1345 }
1346 }
1347
1cda1322 1348 if (_my_tls.locals.exitsock != INVALID_SOCKET)
1fd5e000 1349 {
d134b48f
CF
1350 char buf[1];
1351 si->exitsock = _my_tls.locals.exitsock;
1352 select_printf ("read a byte from %p", si->exitsock);
1353 recv (si->exitsock, buf, 1, 0);
1fd5e000 1354 }
1cda1322 1355 else
1fd5e000 1356 {
1cda1322
CF
1357 si->exitsock = _my_tls.locals.exitsock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
1358 if (_my_tls.locals.exitsock == INVALID_SOCKET)
1359 {
1360 set_winsock_errno ();
1361 select_printf ("cannot create socket, %E");
1362 return -1;
1363 }
1cda1322
CF
1364 int sin_len = sizeof (_my_tls.locals.exitsock_sin);
1365 memset (&_my_tls.locals.exitsock_sin, 0, sin_len);
1366 _my_tls.locals.exitsock_sin.sin_family = AF_INET;
1367 _my_tls.locals.exitsock_sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
1368 if (bind (si->exitsock, (struct sockaddr *) &_my_tls.locals.exitsock_sin, sin_len) < 0)
1369 {
1370 select_printf ("cannot bind socket %p, %E", si->exitsock);
1371 goto err;
1372 }
1fd5e000 1373
1cda1322
CF
1374 if (getsockname (si->exitsock, (struct sockaddr *) &_my_tls.locals.exitsock_sin, &sin_len) < 0)
1375 {
1376 select_printf ("getsockname error");
1377 goto err;
1378 }
1fd5e000
CF
1379 }
1380
1381 select_printf ("exitsock %p", si->exitsock);
1382 WINSOCK_FD_SET ((HANDLE) si->exitsock, &si->readfds);
1383 WINSOCK_FD_SET ((HANDLE) si->exitsock, &si->exceptfds);
7ac61736 1384 stuff->device_specific_socket = (void *) si;
1fd5e000
CF
1385 si->start = &stuff->start;
1386 select_printf ("stuff_start %p", &stuff->start);
1d380f59 1387 si->thread = new cygthread (thread_socket, (LPVOID) si, "select_socket");
b6bd7037
CF
1388 me->h = *si->thread;
1389 return 1;
1fd5e000
CF
1390
1391err:
1392 set_winsock_errno ();
1393 closesocket (si->exitsock);
1394 return -1;
1395}
1396
1397void
9cec3d45 1398socket_cleanup (select_record *, select_stuff *stuff)
1fd5e000 1399{
7ac61736 1400 socketinf *si = (socketinf *) stuff->device_specific_socket;
1fd5e000
CF
1401 select_printf ("si %p si->thread %p", si, si ? si->thread : NULL);
1402 if (si && si->thread)
1403 {
1cda1322
CF
1404 char buf[] = "";
1405 int res = sendto (_my_tls.locals.exitsock, buf, 1, 0,
1406 (sockaddr *) &_my_tls.locals.exitsock_sin,
1407 sizeof (_my_tls.locals.exitsock_sin));
1408 select_printf ("sent a byte to the exit sock %p, res %d", _my_tls.locals.exitsock, res);
1fd5e000 1409 /* Wait for thread to go away */
b6bd7037 1410 si->thread->detach ();
7ac61736 1411 stuff->device_specific_socket = NULL;
1fd5e000
CF
1412 delete si;
1413 }
1414 select_printf ("returning");
1415}
1416
1417select_record *
1418fhandler_socket::select_read (select_record *s)
1419{
1420 if (!s)
1421 {
1422 s = new select_record;
1423 s->startup = start_thread_socket;
1fd5e000
CF
1424 s->verify = verify_true;
1425 s->cleanup = socket_cleanup;
1426 }
1229d4f4 1427 s->peek = peek_socket;
5835f2cf 1428 s->read_ready = saw_shutdown_read ();
476dfb65 1429 s->read_selected = true;
1fd5e000
CF
1430 return s;
1431}
1432
1433select_record *
1434fhandler_socket::select_write (select_record *s)
1435{
1436 if (!s)
1437 {
1438 s = new select_record;
1439 s->startup = start_thread_socket;
1fd5e000
CF
1440 s->verify = verify_true;
1441 s->cleanup = socket_cleanup;
1442 }
476dfb65 1443 s->peek = peek_socket;
56551a9b 1444 s->write_ready = saw_shutdown_write () || connect_state () == unconnected;
476dfb65 1445 s->write_selected = true;
56551a9b 1446 if (connect_state () == connect_pending)
6bb769ef
CV
1447 {
1448 s->except_ready = saw_shutdown_write () || saw_shutdown_read ();
1449 s->except_on_write = true;
1450 }
1fd5e000
CF
1451 return s;
1452}
1453
1454select_record *
1455fhandler_socket::select_except (select_record *s)
1456{
1457 if (!s)
1458 {
1459 s = new select_record;
1460 s->startup = start_thread_socket;
1fd5e000
CF
1461 s->verify = verify_true;
1462 s->cleanup = socket_cleanup;
1463 }
476dfb65 1464 s->peek = peek_socket;
5835f2cf
CF
1465 /* FIXME: Is this right? Should these be used as criteria for except? */
1466 s->except_ready = saw_shutdown_write () || saw_shutdown_read ();
476dfb65 1467 s->except_selected = true;
1fd5e000
CF
1468 return s;
1469}
1470
1471static int
476dfb65 1472peek_windows (select_record *me, bool)
1fd5e000
CF
1473{
1474 MSG m;
1475 HANDLE h;
1476 set_handle_or_return_if_not_open (h, me);
41010c6a
CF
1477
1478 if (me->read_selected && me->read_ready)
1479 return 1;
1480
1fd5e000
CF
1481 if (PeekMessage (&m, (HWND) h, 0, 0, PM_NOREMOVE))
1482 {
476dfb65 1483 me->read_ready = true;
1fd5e000
CF
1484 select_printf ("window %d(%p) ready", me->fd, me->fh->get_handle ());
1485 return 1;
1486 }
1487
1488 select_printf ("window %d(%p) not ready", me->fd, me->fh->get_handle ());
1489 return me->write_ready;
1490}
1491
763f09b9
CF
1492static int
1493verify_windows (select_record *me, fd_set *rfds, fd_set *wfds,
1494 fd_set *efds)
1495{
1496 return peek_windows (me, true);
1497}
1498
1fd5e000
CF
1499select_record *
1500fhandler_windows::select_read (select_record *s)
1501{
1502 if (!s)
1503 {
1504 s = new select_record;
1505 s->startup = no_startup;
1fd5e000 1506 }
763f09b9 1507 s->verify = verify_windows;
1229d4f4 1508 s->peek = peek_windows;
476dfb65
CF
1509 s->read_selected = true;
1510 s->read_ready = false;
1fd5e000 1511 s->h = get_handle ();
476dfb65 1512 s->windows_handle = true;
1fd5e000
CF
1513 return s;
1514}
1515
1516select_record *
1517fhandler_windows::select_write (select_record *s)
1518{
1519 if (!s)
1520 {
1521 s = new select_record;
1522 s->startup = no_startup;
1fd5e000
CF
1523 s->verify = verify_ok;
1524 }
476dfb65 1525 s->peek = peek_windows;
1fd5e000 1526 s->h = get_handle ();
476dfb65
CF
1527 s->write_selected = true;
1528 s->write_ready = true;
1529 s->windows_handle = true;
1fd5e000
CF
1530 return s;
1531}
1532
1533select_record *
1534fhandler_windows::select_except (select_record *s)
1535{
1536 if (!s)
1537 {
1538 s = new select_record;
1539 s->startup = no_startup;
1fd5e000
CF
1540 s->verify = verify_ok;
1541 }
476dfb65 1542 s->peek = peek_windows;
1fd5e000 1543 s->h = get_handle ();
476dfb65
CF
1544 s->except_selected = true;
1545 s->except_ready = true;
1546 s->windows_handle = true;
1fd5e000
CF
1547 return s;
1548}
This page took 0.422068 seconds and 5 git commands to generate.