From b052bf2671137fbae0b70e6950af2beffb076309 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Wed, 27 Jun 2012 21:42:11 +0000 Subject: [PATCH] * cygwait.h (cancelable_wait): Make extern to avoid always including. * select.cc (allocfd_set): Try to make a little more efficient. (cygwin_select): Break into two functions to avoid what seems to be a strange compiler problem with alloca and sel constructor. (select): New function. Always honor return from call_signal_handler. (select_stuff::wait): Always honor return from call_signal_handler. * select.h (select_stuff::select_stuff): Use NULL to initialize pointers rather than 0. --- winsup/cygwin/ChangeLog | 11 ++++++++ winsup/cygwin/cygwait.h | 4 +-- winsup/cygwin/select.cc | 61 +++++++++++++++++++++++------------------ winsup/cygwin/select.h | 8 +++--- 4 files changed, 51 insertions(+), 33 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index eaa6b8c75..e52a02daf 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,14 @@ +2012-06-27 Christopher Faylor + + * cygwait.h (cancelable_wait): Make extern to avoid always including. + * select.cc (allocfd_set): Try to make a little more efficient. + (cygwin_select): Break into two functions to avoid what seems to be a + strange compiler problem with alloca and sel constructor. + (select): New function. Always honor return from call_signal_handler. + (select_stuff::wait): Always honor return from call_signal_handler. + * select.h (select_stuff::select_stuff): Use NULL to initialize + pointers rather than 0. + 2012-06-27 Corinna Vinschen * exceptions.cc (exception::handle): Cast exception code to NTSTATUS diff --git a/winsup/cygwin/cygwait.h b/winsup/cygwin/cygwait.h index 6a004626e..0303ec3b6 100644 --- a/winsup/cygwin/cygwait.h +++ b/winsup/cygwin/cygwait.h @@ -29,11 +29,11 @@ DWORD cancelable_wait (HANDLE, PLARGE_INTEGER timeout = NULL, unsigned = cw_std_mask) __attribute__ ((regparm (3))); -static inline DWORD __attribute__ ((always_inline)) +extern inline DWORD __attribute__ ((always_inline)) cancelable_wait (HANDLE h, DWORD howlong, unsigned mask) { - PLARGE_INTEGER pli_howlong; LARGE_INTEGER li_howlong; + PLARGE_INTEGER pli_howlong; if (howlong == INFINITE) pli_howlong = NULL; else diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc index 0186af733..8d131291e 100644 --- a/winsup/cygwin/select.cc +++ b/winsup/cygwin/select.cc @@ -73,7 +73,13 @@ typedef long fd_mask; #define UNIX_FD_ZERO(p, n) \ memset ((caddr_t) (p), 0, sizeof_fd_set ((n))) -#define allocfd_set(n) ((fd_set *) memset (alloca (sizeof_fd_set (n)), 0, sizeof_fd_set (n))) +#define allocfd_set(n) ({\ + size_t __sfds = sizeof_fd_set (n) + 8; \ + void *__res = alloca (__sfds); \ + memset (__res, 0, __sfds); \ + (fd_set *) __res; \ +}) + #define copyfd_set(to, from, n) memcpy (to, from, sizeof_fd_set (n)); #define set_handle_or_return_if_not_open(h, s) \ @@ -84,31 +90,15 @@ typedef long fd_mask; return -1; \ } -/* The main select code. - */ +static int select (int, fd_set *, fd_set *, fd_set *, DWORD); + +/* The main select code. */ extern "C" int cygwin_select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *to) { select_printf ("select(%d, %p, %p, %p, %p)", maxfds, readfds, writefds, exceptfds, to); - select_stuff sel; - fd_set *dummy_readfds = allocfd_set (maxfds); - fd_set *dummy_writefds = allocfd_set (maxfds); - fd_set *dummy_exceptfds = allocfd_set (maxfds); - - /* Allocate some fd_set structures using the number of fds as a guide. */ - fd_set *r = allocfd_set (maxfds); - fd_set *w = allocfd_set (maxfds); - fd_set *e = allocfd_set (maxfds); - - if (!readfds) - readfds = dummy_readfds; - if (!writefds) - writefds = dummy_writefds; - if (!exceptfds) - exceptfds = dummy_exceptfds; - pthread_testcancel (); /* Convert to milliseconds or INFINITE if to == NULL */ @@ -121,12 +111,33 @@ cygwin_select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, else select_printf ("to NULL, ms %x", ms); - sel.return_on_signal = &_my_tls == _main_tls; + int res = select (maxfds, readfds ?: allocfd_set (maxfds), + writefds ?: allocfd_set (maxfds), + exceptfds ?: allocfd_set (maxfds), ms); + syscall_printf ("%R = select(%d, %p, %p, %p, %p)", res, maxfds, readfds, + writefds, exceptfds, to); + return res; +} +/* This function is arbitrarily split out from cygwin_select to avoid odd + gcc issues with the use of allocfd_set and improper constructor handling + for the sel variable. */ +static int +select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + DWORD ms) +{ int res = select_stuff::select_loop; LONGLONG start_time = gtod.msecs (); /* Record the current time for later use. */ + select_stuff sel; + sel.return_on_signal = 0; + + /* Allocate some fd_set structures using the number of fds as a guide. */ + fd_set *r = allocfd_set (maxfds); + fd_set *w = allocfd_set (maxfds); + fd_set *e = allocfd_set (maxfds); + while (res == select_stuff::select_loop) { /* Build the select record per fd linked list and set state as @@ -146,8 +157,7 @@ cygwin_select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, { case WAIT_SIGNALED: select_printf ("signal received"); - _my_tls.call_signal_handler (); - if (!sel.return_on_signal) + if (_my_tls.call_signal_handler ()) res = select_stuff::select_loop; /* Emulate linux behavior */ else { @@ -199,8 +209,6 @@ cygwin_select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, if (res < -1) res = -1; - syscall_printf ("%R = select(%d, %p, %p, %p, %p)", res, maxfds, readfds, - writefds, exceptfds, to); return res; } @@ -365,8 +373,7 @@ next_while:; be assured that a signal handler won't jump out of select entirely. */ cleanup (); destroy (); - _my_tls.call_signal_handler (); - if (!return_on_signal) + if (_my_tls.call_signal_handler ()) res = select_loop; else { diff --git a/winsup/cygwin/select.h b/winsup/cygwin/select.h index 0afccbd9d..fe0c206d5 100644 --- a/winsup/cygwin/select.h +++ b/winsup/cygwin/select.h @@ -97,9 +97,9 @@ public: select_stuff (): return_on_signal (false), always_ready (false), windows_used (false), start (0), - device_specific_pipe (0), - device_specific_socket (0), - device_specific_serial (0), - device_specific_mailslot (0) {} + device_specific_pipe (NULL), + device_specific_socket (NULL), + device_specific_serial (NULL), + device_specific_mailslot (NULL) {} }; #endif /* _SELECT_H_ */