STINNER Victor added the comment:

@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.)

----------
nosy: +benjamin.peterson

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue23863>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to