New submission from Ondra Kutal <[email protected]>:
At the moment, socket select.select() function is not interruptable on Windows
OS (in main thread). Following code cannot be interrupted (for example by
CTRL+C):
import select, socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setblocking(False)
s.bind(('0.0.0.0', 6666))
s.listen(100)
select.select([s], [], [], None)
s.close()
However this can be achieved by replacing select() calls with use of Windows
native APIs WSAEventSelect and WSAWaitForMultipleEvents (see for example
https://stackoverflow.com/questions/10353017). I have tried a quick prototype
in selectmodule.c, replacing
Py_BEGIN_ALLOW_THREADS
errno = 0;
n = select(max, &ifdset, &ofdset, &efdset, tvp);
Py_END_ALLOW_THREADS
with
#ifndef MS_WINDOWS
Py_BEGIN_ALLOW_THREADS
errno = 0;
n = select(max, &ifdset, &ofdset, &efdset, tvp);
Py_END_ALLOW_THREADS
#else
if (!_PyOS_IsMainThread()) {
Py_BEGIN_ALLOW_THREADS
errno = 0;
n = select(max, &ifdset, &ofdset, &efdset, tvp);
Py_END_ALLOW_THREADS
}
else
{
// quick prototype, only for read sockets
WSAEVENT events[50];
for (u_int i = 0; i < ifdset.fd_count; ++i)
{
events[i+1] = WSACreateEvent();
WSAEventSelect(ifdset.fd_array[i], events[i+1], FD_ACCEPT |
FD_READ);
}
/* putting interrupt event as a first one in the list
*/
events[0] = _PyOS_SigintEvent();
ResetEvent(events[0]);
Py_BEGIN_ALLOW_THREADS
errno = 0;
n = WSAWaitForMultipleEvents(ifdset.fd_count, events, FALSE, tvp ?
(DWORD)_PyTime_AsMilliseconds(timeout, _PyTime_ROUND_CEILING) : WSA_INFINITE,
FALSE);
Py_END_ALLOW_THREADS
if (n == 0)
errno = EINTR;
else if (n == WSA_WAIT_FAILED)
n = SOCKET_ERROR;
else
n = 1; /* prototype implementation, acting like just 1 socket
is ready,
for actual number it will be probably necessary to query
WSAWaitForMultipleEvents
multiple times since it otherwise returns only index of
first ready event...
*/
}
#endif
and then I was able to interrupt the script above. I noticed slight performance
loss when having timeout 0, repeating select 1000 times it took ~2000 us, wile
after this update it took ~3000 us.
I am just throwing it here to consider as a possibility. Clearly my code above
is just proof of concept, modification would be needed (include write fd, some
proper fd limit, possibly check multiple times to get actual number of ready
fds, etc...).
----------
components: Interpreter Core, Windows
messages: 327354
nosy: Ondra Kutal, paul.moore, steve.dower, tim.golden, zach.ware
priority: normal
severity: normal
status: open
title: Consider making Windows select.select interruptable using WSAEventSelect
& WSAWaitForMultipleEvents
type: enhancement
versions: Python 3.8
_______________________________________
Python tracker <[email protected]>
<https://bugs.python.org/issue34934>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com