Dear Wine Developers, Looks like such ignorance is usual practice in wine. I just need to ignore EINTR in one more place. Otherwise our client application is bad working in Wine.
>From 45c8b9f64ff4bb961a34182a5051aaf082c127cd Mon Sep 17 00:00:00 2001 From: Dmitriy Anisimkov <[email protected]> Date: Sun, 1 Feb 2009 14:16:32 +0600 Subject: (WS_select): Ignore poll EINTR result code. --- dlls/ws2_32/socket.c | 39 ++++++++++++++++++++++++++++++++++----- 1 files changed, 34 insertions(+), 5 deletions(-) diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index c3ee046..a50b198 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -389,7 +389,7 @@ static const int ws_eai_map[][2] = MAP_OPTION( EAI_FAIL ), MAP_OPTION( EAI_FAMILY ), MAP_OPTION( EAI_MEMORY ), -/* Note: EAI_NODATA is deprecated, but still +/* Note: EAI_NODATA is deprecated, but still * used by Windows and Linux... We map the newer * EAI_NONAME to EAI_NODATA for now until Windows * changes too. @@ -2788,8 +2788,22 @@ int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds, const struct WS_timeval* ws_timeout) { struct pollfd *pollfds; + struct timeval tv1, tv2, wst; int count, ret, timeout = -1; + struct timeval sub_tv (struct timeval tv1, struct timeval tv2) + { + struct timeval tv; + tv.tv_sec = tv1.tv_sec - tv2.tv_sec; + tv.tv_usec = tv1.tv_usec - tv2.tv_usec; + if (tv.tv_usec < 0) + { + tv.tv_usec += 1000000; + tv.tv_sec -= 1; + } + return tv; + }; + TRACE("read %p, write %p, excp %p timeout %p\n", ws_readfds, ws_writefds, ws_exceptfds, ws_timeout); @@ -2799,9 +2813,24 @@ int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds, return SOCKET_ERROR; } - if (ws_timeout) timeout = (ws_timeout->tv_sec * 1000) + (ws_timeout->tv_usec + 999) / 1000; + if (ws_timeout) + { + timeout = (ws_timeout->tv_sec * 1000) + (ws_timeout->tv_usec + 999) / 1000; + gettimeofday (&tv1, 0); + } - ret = poll( pollfds, count, timeout ); + while ((ret = poll( pollfds, count, timeout )) < 0) + { + if (errno == EINTR && ws_timeout) + { + gettimeofday (&tv2, 0); + wst.tv_sec = ws_timeout->tv_sec; + wst.tv_usec = ws_timeout->tv_usec; + tv2 = sub_tv (wst, sub_tv (tv2, tv1)); + if (tv2.tv_sec < 0 || (tv2.tv_sec == 0 && tv2.tv_usec == 0)) break; + timeout = (tv2.tv_sec * 1000) + (tv2.tv_usec + 999) / 1000; + } else break; + }; release_poll_fds( ws_readfds, ws_writefds, ws_exceptfds, pollfds ); if (ret == -1) SetLastError(wsaErrno()); @@ -5172,7 +5201,7 @@ INT WINAPI WSAAddressToStringA( LPSOCKADDR sockaddr, DWORD len, /*********************************************************************** * WSAAddressToStringW (WS2_32.28) * - * Convert a sockaddr address into a readable address string. + * Convert a sockaddr address into a readable address string. * * PARAMS * sockaddr [I] Pointer to a sockaddr structure. @@ -5254,7 +5283,7 @@ INT WINAPI WSAGetServiceClassInfoA( LPGUID provider, LPGUID service, LPDWORD len FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service), len, info ); WSASetLastError(WSA_NOT_ENOUGH_MEMORY); - return SOCKET_ERROR; + return SOCKET_ERROR; } /*********************************************************************** -- 1.5.6
