modfl-ieee: Fix test failures.
[gnulib.git] / lib / select.c
index de4e3b4..377d549 100644 (file)
@@ -1,7 +1,7 @@
 /* Emulation for select(2)
    Contributed by Paolo Bonzini.
 
-   Copyright 2008-2009 Free Software Foundation, Inc.
+   Copyright 2008-2012 Free Software Foundation, Inc.
 
    This file is part of gnulib.
 
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License along
-   with this program; if not, write to the Free Software Foundation,
-   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+   with this program; if not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include <alloca.h>
 #include <assert.h>
 
 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
-/* Native Win32.  */
+/* Native Windows.  */
 
 #include <sys/types.h>
-#include <stdbool.h>
 #include <errno.h>
 #include <limits.h>
 
 #include <conio.h>
 #include <time.h>
 
+/* Get the overridden 'struct timeval'.  */
+#include <sys/time.h>
+
+#include "msvc-nothrow.h"
+
+#undef select
+
 struct bitset {
   unsigned char in[FD_SETSIZE / CHAR_BIT];
   unsigned char out[FD_SETSIZE / CHAR_BIT];
@@ -77,10 +82,12 @@ typedef DWORD (WINAPI *PNtQueryInformationFile)
 #define PIPE_BUF        512
 #endif
 
-#define IsConsoleHandle(h) (((long) (h) & 3) == 3)
+/* Optimized test whether a HANDLE refers to a console.
+   See <http://lists.gnu.org/archive/html/bug-gnulib/2009-08/msg00065.html>.  */
+#define IsConsoleHandle(h) (((intptr_t) (h) & 3) == 3)
 
 static BOOL
-IsSocketHandle(HANDLE h)
+IsSocketHandle (HANDLE h)
 {
   WSANETWORKEVENTS ev;
 
@@ -94,11 +101,14 @@ IsSocketHandle(HANDLE h)
   return ev.lNetworkEvents != 0xDEADBEEF;
 }
 
-/* Compute output fd_sets for libc descriptor FD (whose Win32 handle is H).  */
+/* Compute output fd_sets for libc descriptor FD (whose Windows handle is
+   H).  */
 
 static int
-win32_poll_handle (HANDLE h, int fd, struct bitset *rbits, struct bitset *wbits,
-                   struct bitset *xbits)
+windows_poll_handle (HANDLE h, int fd,
+                     struct bitset *rbits,
+                     struct bitset *wbits,
+                     struct bitset *xbits)
 {
   BOOL read, write, except;
   int i, ret;
@@ -132,16 +142,19 @@ win32_poll_handle (HANDLE h, int fd, struct bitset *rbits, struct bitset *wbits,
           if (avail)
             read = TRUE;
         }
+      else if (GetLastError () == ERROR_BROKEN_PIPE)
+        ;
 
       else
         {
           /* It was the write-end of the pipe.  Check if it is writable.
              If NtQueryInformationFile fails, optimistically assume the pipe is
-             writable.  This could happen on Win9x, where NtQueryInformationFile
-             is not available, or if we inherit a pipe that doesn't permit
-             FILE_READ_ATTRIBUTES access on the write end (I think this should
-             not happen since WinXP SP2; WINE seems fine too).  Otherwise,
-             ensure that enough space is available for atomic writes.  */
+             writable.  This could happen on Windows 9x, where
+             NtQueryInformationFile is not available, or if we inherit a pipe
+             that doesn't permit FILE_READ_ATTRIBUTES access on the write end
+             (I think this should not happen since Windows XP SP2; WINE seems
+             fine too).  Otherwise, ensure that enough space is available for
+             atomic writes.  */
           memset (&iosb, 0, sizeof (iosb));
           memset (&fpli, 0, sizeof (fpli));
 
@@ -228,6 +241,7 @@ win32_poll_handle (HANDLE h, int fd, struct bitset *rbits, struct bitset *wbits,
 int
 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
             struct timeval *timeout)
+#undef timeval
 {
   static struct timeval tv0;
   static HANDLE hEvent;
@@ -246,7 +260,7 @@ rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
     wait_timeout = INFINITE;
   else
     {
-      wait_timeout = timeout->tv_sec + timeout->tv_usec / 1000;
+      wait_timeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
 
       /* select is also used as a portable usleep.  */
       if (!rfds && !wfds && !xfds)
@@ -366,7 +380,7 @@ rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
 
           /* Poll now.  If we get an event, do not wait below.  */
           if (wait_timeout != 0
-              && win32_poll_handle (h, i, &rbits, &wbits, &xbits))
+              && windows_poll_handle (h, i, &rbits, &wbits, &xbits))
             wait_timeout = 0;
         }
     }
@@ -443,7 +457,7 @@ rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
         {
           /* Not a socket.  */
           nhandles++;
-          win32_poll_handle (h, i, &rbits, &wbits, &xbits);
+          windows_poll_handle (h, i, &rbits, &wbits, &xbits);
           if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
             {
               rc++;
@@ -465,7 +479,7 @@ rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
   return rc;
 }
 
-#else /* ! Native Win32.  */
+#else /* ! Native Windows.  */
 
 #include <sys/select.h>