# HG changeset patch # User Paolo Bonzini # Date 1219993831 -7200 # Node ID e38a464bfa5f2f0f7b348cf9dfd24e335ac388e1 # Parent 36c242cddd0674ea0ca35183aa24f9e501db85a0 Revert "poll-win32" This reverts commit 4ced5d92be93b997c280be8d436e8a49b3b5e0dc which was merged in by mistake. diff --git a/lib/poll.c b/lib/poll.c --- a/lib/poll.c +++ b/lib/poll.c @@ -25,18 +25,9 @@ #include "poll.h" #include #include - -#ifdef __MSVCRT__ -#include -#include -#include -#include -#include -#else #include #include #include -#endif #ifdef HAVE_SYS_IOCTL_H #include @@ -57,215 +48,12 @@ #define MSG_PEEK 0 #endif -#ifdef __MSVCRT__ - -/* Declare data structures for ntdll functions. */ -typedef struct _FILE_PIPE_LOCAL_INFORMATION { - ULONG NamedPipeType; - ULONG NamedPipeConfiguration; - ULONG MaximumInstances; - ULONG CurrentInstances; - ULONG InboundQuota; - ULONG ReadDataAvailable; - ULONG OutboundQuota; - ULONG WriteQuotaAvailable; - ULONG NamedPipeState; - ULONG NamedPipeEnd; -} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION; - -typedef struct _IO_STATUS_BLOCK -{ - union u { - NTSTATUS Status; - PVOID Pointer; - }; - ULONG_PTR Information; -} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; - -#define FilePipeLocalInformation 24 - -typedef NTSTATUS (NTAPI *PNtQueryInformationFile) - (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS); - -#ifndef PIPE_BUF -#define PIPE_BUF 512 -#endif - -/* Compute revents values for file handle H. */ - -static int -win32_compute_revents (HANDLE h, int sought) -{ - int i, ret, happened; - INPUT_RECORD *irbuffer; - DWORD avail, nbuffer; - IO_STATUS_BLOCK iosb; - FILE_PIPE_LOCAL_INFORMATION fpli; - static PNtQueryInformationFile NtQueryInformationFile; - - ret = WaitForSingleObject (h, 0); - if (ret != WAIT_OBJECT_0) - return sought & (POLLOUT | POLLWRNORM | POLLWRBAND); - - switch (GetFileType (h)) - { - case FILE_TYPE_PIPE: - if (!NtQueryInformationFile) - NtQueryInformationFile = (PNtQueryInformationFile) - GetProcAddress (GetModuleHandle ("ntdll.dll"), - "NtQueryInformationFile"); - - happened = 0; - if (!PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL)) - return POLLERR; - - if (avail) - happened |= sought & (POLLIN | POLLRDNORM); - - memset (&iosb, 0, sizeof (iosb)); - memset (&fpli, 0, sizeof (fpli)); - - /* If NtQueryInformationFile fails, optimistically assume the pipe is - writable. This could happen on Win9x, because 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. */ - if (NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli), - FilePipeLocalInformation) - || fpli.WriteQuotaAvailable >= PIPE_BUF - || (fpli.OutboundQuota < PIPE_BUF && - fpli.WriteQuotaAvailable == fpli.OutboundQuota)) - happened |= sought & (POLLOUT | POLLWRNORM | POLLWRBAND); - - return happened; - - case FILE_TYPE_CHAR: - nbuffer = avail = 0; - bRet = GetNumberOfConsoleInputEvents (h, &nbuffer); - if (!bRet || nbuffer == 0) - return POLLHUP; - - irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD)); - bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail); - if (!bRet || avail == 0) - return POLLHUP; - - for (i = 0; i < avail; i++) - if (irbuffer[i].EventType == KEY_EVENT) - return sought & ~(POLLPRI | POLLRDBAND); - - return sought & (POLLOUT | POLLWRNORM | POLLWRBAND); - - default: - return sought & ~(POLLPRI | POLLRDBAND); - } -} - -/* Convert fd_sets returned by select into revents values. */ - -static int -win32_compute_revents_socket (SOCKET h, int sought, - fd_set *rfds, fd_set *wfds, fd_set *efds) -{ - int happened = 0; - - if (FD_ISSET (h, rfds)) - { - int r, error; - - char data[64]; - WSASetLastError (0); - r = recv (h, data, sizeof (data), MSG_PEEK); - error = WSAGetLastError (); - WSASetLastError (0); - - if (r == 0) - happened |= POLLHUP; - - /* If the event happened on an unconnected server socket, - that's fine. */ - else if (r > 0 || ( /* (r == -1) && */ error == ENOTCONN)) - happened |= (POLLIN | POLLRDNORM) & sought; - - /* Distinguish hung-up sockets from other errors. */ - else if (error == WSAESHUTDOWN || error == WSAECONNRESET - || error == WSAECONNABORTED || error == WSAENETRESET) - happened |= POLLHUP; - - else - happened |= POLLERR; - } - - if (FD_ISSET (h, wfds)) - happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought; - - if (FD_ISSET (h, efds)) - happened |= (POLLPRI | POLLRDBAND) & sought; - - return happened; -} - -#else /* !MinGW */ - -/* Convert select(2) returned fd_sets into poll(2) revents values. */ -static int -compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds) -{ - int happened; - if (FD_ISSET (fd, rfds)) - { - int r; - int socket_errno; - -#if defined __MACH__ && defined __APPLE__ - /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK - for some kinds of descriptors. Detect if this descriptor is a - connected socket, a server socket, or something else using a - 0-byte recv, and use ioctl(2) to detect POLLHUP. */ - r = recv (fd, NULL, 0, MSG_PEEK); - socket_errno = (r < 0) ? errno : 0; - if (r == 0 || socket_errno == ENOTSOCK) - ioctl (fd, FIONREAD, &r); -#else - char data[64]; - r = recv (fd, data, sizeof (data), MSG_PEEK); - socket_errno = (r < 0) ? errno : 0; -#endif - if (r == 0) - happened |= POLLHUP; - - /* If the event happened on an unconnected server socket, - that's fine. */ - else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN)) - happened |= (POLLIN | POLLRDNORM) & sought; - - /* Distinguish hung-up sockets from other errors. */ - else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET - || socket_errno == ECONNABORTED || socket_errno == ENETRESET) - happened |= POLLHUP; - - else - happened |= POLLERR; - } - - if (FD_ISSET (fd, wfds)) - happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought; - - if (FD_ISSET (fd, efds)) - happened |= (POLLPRI | POLLRDBAND) & sought; - - return happened; -} -#endif /* !MinGW */ - int poll (pfd, nfd, timeout) struct pollfd *pfd; nfds_t nfd; int timeout; { -#ifndef __MSVCRT__ fd_set rfds, wfds, efds; struct timeval tv; struct timeval *ptv; @@ -374,8 +162,49 @@ pfd[i].revents = 0; else { - int happened = compute_revents (pfd[i].fd, pfd[i].events, - &rfds, &wfds, &efds); + int happened = 0, sought = pfd[i].events; + if (FD_ISSET (pfd[i].fd, &rfds)) + { + int r; + int socket_errno; + +#if defined __MACH__ && defined __APPLE__ + /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK + for some kinds of descriptors. Detect if this descriptor is a + connected socket, a server socket, or something else using a + 0-byte recv, and use ioctl(2) to detect POLLHUP. */ + r = recv (pfd[i].fd, NULL, 0, MSG_PEEK); + socket_errno = (r < 0) ? errno : 0; + if (r == 0 || socket_errno == ENOTSOCK) + ioctl(pfd[i].fd, FIONREAD, &r); +#else + char data[64]; + r = recv (pfd[i].fd, data, sizeof (data), MSG_PEEK); + socket_errno = (r < 0) ? errno : 0; +#endif + if (r == 0) + happened |= POLLHUP; + + /* If the event happened on an unconnected server socket, + that's fine. */ + else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN)) + happened |= (POLLIN | POLLRDNORM) & sought; + + /* Distinguish hung-up sockets from other errors. */ + else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET + || socket_errno == ECONNABORTED || socket_errno == ENETRESET) + happened |= POLLHUP; + + else + happened |= POLLERR; + } + + if (FD_ISSET (pfd[i].fd, &wfds)) + happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought; + + if (FD_ISSET (pfd[i].fd, &efds)) + happened |= (POLLPRI | POLLRDBAND) & sought; + if (happened) { pfd[i].revents = happened; @@ -384,143 +213,4 @@ } return rc; -#else - fd_set rfds, wfds, efds; - static struct timeval tv0; - struct timeval tv = { 0, 0 }; - struct timeval *ptv; - static HANDLE hEvent; - HANDLE handle_array[FD_SET_SIZE + 2]; - DWORD ret, wait_timeout, nhandles; - int nsock; - BOOL bRet; - MSG msg; - char sockbuf[256]; - int rc; - nfds_t i; - - if (nfd < 0 || nfd > FD_SET_SIZE || timeout < 0) - { - errno = EINVAL; - return -1; - } - - if (!hEvent) - hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); - - handle_array[0] = hEvent; - nhandles = 1; - nsock = 0; - - /* Classify socket handles and create fd sets. */ - FD_ZERO (&rfds); - FD_ZERO (&wfds); - FD_ZERO (&efds); - for (i = 0; i < nfd; i++) - { - if (pfd[i].fd < 0) - continue; - - h = (HANDLE) _get_osfhandle (i); - assert (h != NULL); - optlen = sizeof(sockbuf); - if ((getsockopt ((SOCKET) h, SOL_SOCKET, SO_TYPE, sockbuf, &optlen) - != SOCKET_ERROR) - || WSAGetLastError() != WSAENOTSOCK) - { - int ev = 0; - - /* see above; socket handles are mapped onto select. */ - if (pfd[i].events & (POLLIN | POLLRDNORM)) - { - FD_SET (pfd[i].fd, &rfds); - ev |= FD_READ | FD_ACCEPT; - } - if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND)) - { - FD_SET (pfd[i].fd, &wfds); - ev |= FD_WRITE | FD_CONNECT; - } - if (pfd[i].events & (POLLPRI | POLLRDBAND)) - { - FD_SET (pfd[i].fd, &efds); - ev |= FD_OOB; - } - if (ev) - { - WSAEventSelect ((SOCKET) h, hEvent, ev); - nsock++; - } - } - else - { - if (pfd[i].events & (POLLIN | POLLRDNORM | - POLLOUT | POLLWRNORM | POLLWRBAND)) - handle_array[nhandles++] = h; - } - } - - if (timeout == INFTIM) - wait_timeout = INFINITE; - else - wait_timeout = timeout; - - for (;;) - { - ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE, - wait_timeout, QS_ALLINPUT); - - if (ret == WAIT_OBJECT_0 + nhandles) - { - /* new input of some other kind */ - while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0) - { - TranslateMessage (&msg); - DispatchMessage (&msg); - } - } - else - break; - } - - /* Now check if the sockets have some event set. */ - select (nsock + 1, rfds, wfds, efds, &tv0); - - /* Place a sentinel at the end of the array. */ - handle_array[nhandles] = NULL; - nhandles = 1; - for (i = 0; i < nfd; i++) - { - int happened; - - if (pfd[i].fd < 0) - { - pfd[i].revents = 0; - continue; - } - - h = (HANDLE) _get_osfhandle (i); - if (h != handle_array[nhandles]) - { - /* It's a socket. */ - WSAEventSelect (h, 0, 0); - happened = win32_compute_revents_socket ((SOCKET) h, pfd[i].events, - &rfds, &wfds, &efds); - } - else - { - /* Not a socket. */ - nhandles++; - happened = win32_compute_revents (h, pfd[i].events); - } - - if (happened) - { - pfd[i].revents = happened; - rc++; - } - } - - return rc; -#endif }