Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2012-06-28 01:42:11 +0400
committerChristopher Faylor <me@cgf.cx>2012-06-28 01:42:11 +0400
commitb052bf2671137fbae0b70e6950af2beffb076309 (patch)
tree14ee283644bcd31247927959f8b1fa72d75b0045 /winsup/cygwin/select.cc
parentc60437258a05fddbb9994e8714691ffc0bfd606e (diff)
* 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.
Diffstat (limited to 'winsup/cygwin/select.cc')
-rw-r--r--winsup/cygwin/select.cc61
1 files changed, 34 insertions, 27 deletions
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
{