This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Windows select() errors out when given no fds to select on, which breaks SelectSelector
Type: behavior Stage: needs patch
Components: Library (Lib), Windows Versions: Python 3.10, Python 3.9, Python 3.8
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: berker.peksag, eryksun, giampaolo.rodola, njs, paul.moore, steve.dower, tim.golden, zach.ware
Priority: normal Keywords:

Created on 2017-01-12 23:42 by njs, last changed 2022-04-11 14:58 by admin.

Messages (5)
msg285353 - (view) Author: Nathaniel Smith (njs) * (Python committer) Date: 2017-01-12 23:42
If SelectSelector.select() is called when there are no fds registered, then it ends up calling select.select([], [], [], timeout).

On sensible operating systems, this is equivalent to time.sleep(timeout). On Windows, it raises an error. Asyncio manages to avoid hitting this due to the fact that it always has at least one fd registered, but it causes problems for other users of the selectors module, e.g.:
  https://github.com/dabeaz/curio/issues/75

I see two possible approaches to fixing this:

1) Modify SelectSelector to check for this case and call time.sleep() instead of select.select() when encountered.

2) Modify the select.select() wrapper so that it behaves consistently on all operating systems, by special-casing this situation on Windows.

Option (2) seems nicer to me.
msg285497 - (view) Author: Eryk Sun (eryksun) * (Python triager) Date: 2017-01-14 19:42
Some WinSock functions are just dispatchers that call a provider function. The dispatch table is set up when WinSock (i.e. ws2_32.dll) calls the WSPStartup function [1] of a provider DLL (e.g. mswsock.dll). In the case of select(), it calls the socket provider's WSPSelect function [2]. It determines the provider from the first socket found in the order of readfds, writefds, and exceptfds. It fails if there isn't at least one socket from which it can determine the provider. Also, given this design, each socket in all three sets has to be from the same provider. 

In general, using a dummy socket isn't a good workaround for using select() to implement a sleep function. WSPSelect can't be interrupted (or rather, it can only be interrupted temporarily to execute an asynchronous procedure call that's queued to the thread via QueueUserAPC, after which it resumes waiting). If a script uses select() with a dummy socket to sleep on the main thread, the user won't be able to cancel the wait with Ctrl+C. It would be better in this case if select.select waited on the SIGINT event like the Windows implementation of time.sleep.

[1]: https://msdn.microsoft.com/en-us/library/ms742296
[2]: https://msdn.microsoft.com/en-us/library/ms742289
msg287222 - (view) Author: Berker Peksag (berker.peksag) * (Python committer) Date: 2017-02-07 09:59
See http://bugs.python.org/issue25680#msg255116 for Guido's comment on platform differences.
msg287223 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2017-02-07 10:14
> 2) Modify the select.select() wrapper so that it behaves consistently on all operating systems, by special-casing this situation on Windows.

Please don't do that. In Python, we have a long tradition of trying to provide thin wrappers to OS functions: os and select modules are good example.

To abstract the OS, there are higher level modules like: os=>shutil and select=>selectors.

About the Windows issue: I don't know what is the best fix (if any). The minimum change is to document Windows's special case in Python doc.
msg287225 - (view) Author: Nathaniel Smith (njs) * (Python committer) Date: 2017-02-07 10:48
> Please don't do that. In Python, we have a long tradition of trying to provide thin wrappers to OS functions: os and select modules are good example.

I don't find this argument terribly convincing... Python also has a long history of papering over small issues when it can be done in a simple and tasteful way. select.select already overrides the Windows default for the maximum number of FDs, and the PEP 475 retry logic is definitely a non-trivial modification to the raw OS select semantics.

But I don't think it matters terribly much either, so long as we all agree that the SelectSelector behavior is definitely a bug :-)
History
Date User Action Args
2022-04-11 14:58:41adminsetgithub: 73442
2021-03-12 21:41:22vstinnersetnosy: - vstinner
2021-03-12 21:34:20eryksunsetversions: + Python 3.8, Python 3.9, Python 3.10, - Python 3.5, Python 3.6, Python 3.7
2019-04-25 21:37:17martin.panterlinkissue36726 superseder
2017-07-30 19:15:23pitrousettype: behavior
stage: needs patch
2017-07-27 01:24:41giampaolo.rodolasetnosy: + giampaolo.rodola
2017-02-07 10:48:22njssetmessages: + msg287225
2017-02-07 10:14:44vstinnersetmessages: + msg287223
2017-02-07 10:12:40vstinnersetnosy: + vstinner
2017-02-07 09:59:30berker.peksagsetnosy: + berker.peksag
messages: + msg287222
2017-01-14 19:42:36eryksunsetnosy: + paul.moore, tim.golden, eryksun, zach.ware, steve.dower
messages: + msg285497
components: + Windows
2017-01-12 23:42:18njscreate