http://bugs.winehq.org/show_bug.cgi?id=14195
Summary: EINTR in WS_select Product: Wine Version: CVS/GIT Platform: Other OS/Version: other Status: UNCONFIRMED Severity: major Priority: P2 Component: winsock AssignedTo: wine-bugs@winehq.org ReportedBy: anisimkov@ada-ru.org
I have an Win32 application written in Borland Delphi using Eureka tool (http://www.eurekalog.com/) working in Wine but with one error. If exception occured in main thread, WinAPI 'select' call in secondary thread interrupted with WSAINTR error code. The short Delphi example is in the attached sample.tar.bz2.
WSAINTR result in Win32 select mean
"A blocking Windows Socket 1.1 call was canceled through WSACancelBlockingCall." (http://msdn.microsoft.com/en-us/library/ms740141(VS.85).aspx)
But
"The WSACancelBlockingCall function has been removed in compliance with the Windows Sockets 2 specification, revision 2.2.0. The function is not exported directly by WS2_32.DLL and Windows Sockets 2 applications should not use this function. Windows Sockets 1.1 applications that call this function are still supported through the WINSOCK.DLL and WSOCK32.DLL." (http://msdn.microsoft.com/en-us/library/ms741547(VS.85).aspx)
Wine translates EINTR error code into WSAINTR error code. But in Linux EINTR have a different meaning
"EINTR A signal occurred before any requested event." (man poll)
I propose the following patch to ignore the EINTR error code in Wine 'WS_select' based on Linux poll call:
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index fa908b4..a98717e 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -2591,7 +2591,10 @@ int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
if (ws_timeout) timeout = (ws_timeout->tv_sec * 1000) + (ws_timeout->tv_usec + 999) / 1000;
- ret = poll( pollfds, count, timeout ); + while ((ret = poll( pollfds, count, timeout )) < 0) + { + if (errno != EINTR) break; + }; release_poll_fds( ws_readfds, ws_writefds, ws_exceptfds, pollfds );
if (ret == -1) SetLastError(wsaErrno());
The wine already have a similar EINTR ignore
git-diff 84232099^ 84232099 -- dlls/winsock/socket.c index cfbf49f..0f1ba34 100644 --- a/dlls/winsock/socket.c +++ b/dlls/winsock/socket.c @@ -589,7 +589,13 @@ static inline int do_block( int fd, int events )
pfd.fd = fd; pfd.events = events; - poll(&pfd, 1, -1); + + while (poll(&pfd, 1, -1) < 0) + { + if (errno != EINTR) + return -1; + } + return pfd.revents; }
Thank you for attension and for great software. Best regards.
Dmitriy Anisimkov.