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