maint: update copyright
[gnulib.git] / lib / poll.c
index 7c52cb6..e9e9eb9 100644 (file)
@@ -1,7 +1,7 @@
 /* Emulation for poll(2)
    Contributed by Paolo Bonzini.
 
-   Copyright 2001-2003, 2006-2010 Free Software Foundation, Inc.
+   Copyright 2001-2003, 2006-2014 Free Software Foundation, Inc.
 
    This file is part of gnulib.
 
@@ -16,8 +16,7 @@
    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/>.  */
 
 /* Tell gcc not to warn about the (nfd < 0) tests, below.  */
 #if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__
 #include <alloca.h>
 
 #include <sys/types.h>
-#include "poll.h"
+
+/* Specification.  */
+#include <poll.h>
+
 #include <errno.h>
 #include <limits.h>
 #include <assert.h>
 
 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
-# define WIN32_NATIVE
+# define WINDOWS_NATIVE
 # include <winsock2.h>
 # include <windows.h>
 # include <io.h>
 # include <stdio.h>
 # include <conio.h>
+# include "msvc-nothrow.h"
 #else
 # include <sys/time.h>
 # include <sys/socket.h>
 # define MSG_PEEK 0
 #endif
 
-#ifdef WIN32_NATIVE
+#ifdef WINDOWS_NATIVE
 
-#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)
@@ -122,7 +127,7 @@ typedef DWORD (WINAPI *PNtQueryInformationFile)
    for the handle, eliminate them from *P_SOUGHT.  */
 
 static int
-win32_compute_revents (HANDLE h, int *p_sought)
+windows_compute_revents (HANDLE h, int *p_sought)
 {
   int i, ret, happened;
   INPUT_RECORD *irbuffer;
@@ -157,11 +162,12 @@ win32_compute_revents (HANDLE h, int *p_sought)
         {
           /* 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));
 
@@ -220,7 +226,7 @@ win32_compute_revents (HANDLE h, int *p_sought)
 /* Convert fd_sets returned by select into revents values.  */
 
 static int
-win32_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
+windows_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
 {
   int happened = 0;
 
@@ -297,6 +303,10 @@ compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
                || socket_errno == ECONNABORTED || socket_errno == ENETRESET)
         happened |= POLLHUP;
 
+      /* some systems can't use recv() on non-socket, including HP NonStop */
+      else if (socket_errno == ENOTSOCK)
+        happened |= (POLLIN | POLLRDNORM) & sought;
+
       else
         happened |= POLLERR;
     }
@@ -312,12 +322,9 @@ compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
 #endif /* !MinGW */
 
 int
-poll (pfd, nfd, timeout)
-     struct pollfd *pfd;
-     nfds_t nfd;
-     int timeout;
+poll (struct pollfd *pfd, nfds_t nfd, int timeout)
 {
-#ifndef WIN32_NATIVE
+#ifndef WINDOWS_NATIVE
   fd_set rfds, wfds, efds;
   struct timeval tv;
   struct timeval *ptv;
@@ -347,7 +354,7 @@ poll (pfd, nfd, timeout)
 
   /* EFAULT is not necessary to implement, but let's do it in the
      simplest case. */
-  if (!pfd)
+  if (!pfd && nfd)
     {
       errno = EFAULT;
       return -1;
@@ -452,6 +459,7 @@ poll (pfd, nfd, timeout)
   if (!hEvent)
     hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
 
+restart:
   handle_array[0] = hEvent;
   nhandles = 1;
   FD_ZERO (&rfds);
@@ -499,9 +507,9 @@ poll (pfd, nfd, timeout)
         {
           /* Poll now.  If we get an event, do not poll again.  Also,
              screen buffer handles are waitable, and they'll block until
-             a character is available.  win32_compute_revents eliminates
+             a character is available.  windows_compute_revents eliminates
              bits for the "wrong" direction. */
-          pfd[i].revents = win32_compute_revents (h, &sought);
+          pfd[i].revents = windows_compute_revents (h, &sought);
           if (sought)
             handle_array[nhandles++] = h;
           if (pfd[i].revents)
@@ -577,14 +585,14 @@ poll (pfd, nfd, timeout)
           if (FD_ISSET ((SOCKET) h, &xfds))
             ev.lNetworkEvents |= FD_OOB;
 
-          happened = win32_compute_revents_socket ((SOCKET) h, pfd[i].events,
-                                                   ev.lNetworkEvents);
+          happened = windows_compute_revents_socket ((SOCKET) h, pfd[i].events,
+                                                     ev.lNetworkEvents);
         }
       else
         {
           /* Not a socket.  */
           int sought = pfd[i].events;
-          happened = win32_compute_revents (h, &sought);
+          happened = windows_compute_revents (h, &sought);
           nhandles++;
         }
 
@@ -592,6 +600,12 @@ poll (pfd, nfd, timeout)
         rc++;
     }
 
+  if (!rc && timeout == INFTIM)
+    {
+      SleepEx (1, TRUE);
+      goto restart;
+    }
+
   return rc;
 #endif
 }