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.

Author vstinner
Recipients benjamin.peterson, gregory.p.smith, mcjeff, vstinner
Date 2015-04-14.08:50:50
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1429001451.22.0.0449818804036.issue23863@psf.upfronthosting.co.za>
In-reply-to
Content
@Benjamin: since you are the maintainer of Python 2.7, I would like your opinion on this issue.

Python older than 3.5 does not handle EINTR for you: if you register a signal handler for a signal, the signal handler does not raise an exception, and a syscall is interrupted by a signal: Python raises an exception with the EINTR error code (it may be an OSError, IOError, socket.error, etc.). Well, the longer rationale is in the PEP 475.

Basically, Jeff McNeil wants to implement the PEP 475 in Python 2.7. I'm opposed to that because I contributed to the implementation in Python 3.5 and it changed a *lot* of code, the implementation was only made possible with previous changes done in Python 3.3 and 3.4 like the introduction of time.monotonic() in Python, a monotonic clock in C (the new _PyTime_t API and the _PyTime_GetMonotonicClock()) and refactoring of code.

Retrying socket methods doesn't simply mean writing a loop: you must respect the timeout, which is more complex. Socket methods in Python are implemented internally with select(). select() can fail with EINTR, as socket functions.

Jeff wrote a function to retry on EINTR which recomputes the timeout: socket_eintr.5.patch. Problem: his patch calls socket.settimeout() which is not thread safe. IMO the correct fix is to implement the PEP 475 in socketmodule.c directly, because it makes possible to use a variable for the timeout (no need to call settimeout()). (Reimplementing select() in socket.py to wait until the socket becomes readable/writable doesn't sound right to me; and it would add a new dependency from the socket module to the select module.)

Modifying the C code is more complex: see for example my patch connect_eintr-py27.patch to handle EINTR in socket.connect() and recompute the timeout. IMO socket.connect() requires the most complex code to handle EINTR and recompute the timeout, you have to combine connect(), select() and getsockopt(). (So it's maybe not the best example.) In Python 3.5, it took me ~10 commits to refactor socketmodule.c to be able to add a new sock_call() function (and a few more commits to fix bugs :-))

Since Python didn't handle EINTR before Python 3.5 and only a very few people complained, I don't think that it's worth to take the risk on introduction regressions. Anyway, Python 2 is dead, Python 3 is the place where large bugfixes are implemented (and where new features are implemented).

The PEP 475 is much larger than the socket module. In Python 2.7, io, os, select, socket and time are also impacted for example.

I suggest to close this issue as WONTFIX.

I'm not sure that only fixing socket.connect() is useful. (Apply connect_eintr-py27.patch which is based on my fix for Python 3.5.)
History
Date User Action Args
2015-04-14 08:50:51vstinnersetrecipients: + vstinner, gregory.p.smith, benjamin.peterson, mcjeff
2015-04-14 08:50:51vstinnersetmessageid: <1429001451.22.0.0449818804036.issue23863@psf.upfronthosting.co.za>
2015-04-14 08:50:51vstinnerlinkissue23863 messages
2015-04-14 08:50:50vstinnercreate