You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
File "test.py", line 62, in <module>
result = do_lqs(client, str(dnvn))
File "test.py", line 25, in do_lqs
qualif_service_id = client.create('ti.qualif.service', {})
File "/srv/openerp/.buildout/eggs/ERPpeek-1.4.5-py2.6.egg/erppeek.py", line 894, in wrapper
return self.execute(obj, method, *params, **kwargs)
File "/srv/openerp/.buildout/eggs/ERPpeek-1.4.5-py2.6.egg/erppeek.py", line 636, in execute
res = self._execute(obj, method, *params)
File "/srv/openerp/.buildout/eggs/ERPpeek-1.4.5-py2.6.egg/erppeek.py", line 361, in <lambda>
wrapper = lambda s, *args: s._dispatch(name, args)
File "/usr/lib/python2.6/xmlrpclib.py", line 1489, in __request
verbose=self.__verbose
File "/usr/lib/python2.6/xmlrpclib.py", line 1235, in request
self.send_content(h, request_body)
File "/usr/lib/python2.6/xmlrpclib.py", line 1349, in send_content
connection.endheaders()
File "/usr/lib/python2.6/httplib.py", line 908, in endheaders
self._send_output()
File "/usr/lib/python2.6/httplib.py", line 780, in _send_output
self.send(msg)
File "/usr/lib/python2.6/httplib.py", line 739, in send
self.connect()
File "/usr/lib/python2.6/httplib.py", line 1112, in connect
sock = socket.create_connection((self.host, self.port), self.timeout)
File "/usr/lib/python2.6/socket.py", line 561, in create_connection
raise error, msg
socket.error: [Errno 4] Interrupted system call
We encountered the same problem, this is in the context of using PyQt (specifically QProcess) or twisted. They both rely on SIGCHLD for their notification framework.
I've attached a httplib EINTR patch for 2.6.4 & 2.7.3.
Traceback (most recent call last):
File "./repro1.py", line 22, in <module>
go()
File "./repro1.py", line 18, in go
connection.connect()
File ".../lib/python2.7/httplib.py", line 757, in connectself.timeout, self.source_address)
File ".../lib/python2.7/socket.py", line 571, in create_connectionraise err
socket.error:
neologix commented on May 20, 2014
neologixmannequin
Mannequin
More actions
As said in a previous comment, we don't want to have EINTR handling
code everywhere.
The right way to do this is to handle it at the syscall level.
@tholzer, to clarify Charles-François's comment: EINTR should be handled in socket.connect() and socket.getaddrinfo() (the two syscalls called by create_connection(), AFAIR).
tholzer commented on May 26, 2014
tholzermannequin
Mannequin
More actions
No problem, I've attached a patch for socket.py for Python 2.7.3.
A few notes:
getaddrinfo (and gethostbyname, etc.) are already immune to this bug, so I've just fixed the connect() call.
The socket does need to be closed after EINTR, otherwise a EINPROGRESS might get returned on subsequent connect() calls.
tholzer commented on May 26, 2014
tholzermannequin
Mannequin
More actions
I've also attached a potential patch for the C module Modules/socketmodule.c inside internal_connect().
A few notes:
This seems to work both without time-out and with time-out sockets (non-blocking).
One concern would be a signal storm prolonging the operation beyond the time-out. Should we keep track of the actual time taken in this loop and check it against the 'timeout' parameter ?
Also, I don't think we can call PyErr_CheckSignals() in this context. Does this need to happen at all ?
Thank you for your comment.
So we just only modify the socket.py to handle the system level call, is it right?
Please let me attach the patch file of socket.py for 2.7.2.
tholzer commented on May 29, 2014
tholzermannequin
Mannequin
More actions
Oops, I missed a break statement at the end of socket_2.7.3_eintr_patch.py. I've fixed this now in the attached patch.
The issue is just an example of the main issue bpo-18885 which proposes to retry interrupted syscalls. I hesitate to mark it as duplicate, but it contains an interesting patch.
This issue was fixed in Python 3.5 as part of the PEP-475: see issue bpo-23618 which modified socket.socket.connect() to handle EINTR. It's not as simple as retrying connect() in a loop. You must respect the socket timeout (it's better to have a monotonic clock here, it's now always the case in Python 3.5). When connect() returns EINTR, the connection runs asynchronously, you have to call select() to wait until the connection completes or fails. Then you have to call getsockopt() to get the socket error code.
bpo-20611-connect-eintr-gps01.diff calls again connect() if connect() failed with EINTR. According to the issue bpo-23618, it might work on some platforms, but it's not portable.
For Python 2.7 and 3.4, instead of fixing socket.socket.connect(), which requires complex code, we may only workaround the issue in create_connection(). If connect() raises OSError(EINTR), drop the socket and retry with a fresh connection in a loop until the connection completes or raises a different exception. (And do that for each address.)
Activity
florentx commentedon Feb 12, 2014
I had this sporadic traceback in a project:
File "test.py", line 62, in <module>
result = do_lqs(client, str(dnvn))
File "test.py", line 25, in do_lqs
qualif_service_id = client.create('ti.qualif.service', {})
File "/srv/openerp/.buildout/eggs/ERPpeek-1.4.5-py2.6.egg/erppeek.py", line 894, in wrapper
return self.execute(obj, method, *params, **kwargs)
File "/srv/openerp/.buildout/eggs/ERPpeek-1.4.5-py2.6.egg/erppeek.py", line 636, in execute
res = self._execute(obj, method, *params)
File "/srv/openerp/.buildout/eggs/ERPpeek-1.4.5-py2.6.egg/erppeek.py", line 361, in <lambda>
wrapper = lambda s, *args: s._dispatch(name, args)
File "/usr/lib/python2.6/xmlrpclib.py", line 1489, in __request
verbose=self.__verbose
File "/usr/lib/python2.6/xmlrpclib.py", line 1235, in request
self.send_content(h, request_body)
File "/usr/lib/python2.6/xmlrpclib.py", line 1349, in send_content
connection.endheaders()
File "/usr/lib/python2.6/httplib.py", line 908, in endheaders
self._send_output()
File "/usr/lib/python2.6/httplib.py", line 780, in _send_output
self.send(msg)
File "/usr/lib/python2.6/httplib.py", line 739, in send
self.connect()
File "/usr/lib/python2.6/httplib.py", line 1112, in connect
sock = socket.create_connection((self.host, self.port), self.timeout)
File "/usr/lib/python2.6/socket.py", line 561, in create_connection
raise error, msg
socket.error: [Errno 4] Interrupted system call
It seems that the EINTR should be caught by the standard library in all cases: http://bugs.python.org/issue1628205
But it's not the case for the "socket.create_connection" method (verified in 3.3 and 2.7 source code).
neologix commentedon Feb 13, 2014
Yes, it should.
It's not the case for *almost all* syscalls.
See http://bugs.python.org/issue18885
tholzer commentedon May 20, 2014
We encountered the same problem, this is in the context of using PyQt (specifically QProcess) or twisted. They both rely on SIGCHLD for their notification framework.
I've attached a httplib EINTR patch for 2.6.4 & 2.7.3.
tholzer commentedon May 20, 2014
Here is a reproducible test case:
Which gives:
neologix commentedon May 20, 2014
As said in a previous comment, we don't want to have EINTR handling
code everywhere.
The right way to do this is to handle it at the syscall level.
pitrou commentedon May 20, 2014
@tholzer, to clarify Charles-François's comment: EINTR should be handled in socket.connect() and socket.getaddrinfo() (the two syscalls called by create_connection(), AFAIR).
tholzer commentedon May 26, 2014
No problem, I've attached a patch for socket.py for Python 2.7.3.
A few notes:
getaddrinfo (and gethostbyname, etc.) are already immune to this bug, so I've just fixed the connect() call.
The socket does need to be closed after EINTR, otherwise a EINPROGRESS might get returned on subsequent connect() calls.
tholzer commentedon May 26, 2014
I've also attached a potential patch for the C module Modules/socketmodule.c inside internal_connect().
A few notes:
This seems to work both without time-out and with time-out sockets (non-blocking).
One concern would be a signal storm prolonging the operation beyond the time-out. Should we keep track of the actual time taken in this loop and check it against the 'timeout' parameter ?
Also, I don't think we can call PyErr_CheckSignals() in this context. Does this need to happen at all ?
meishao commentedon May 29, 2014
http://bugs.python.org/issue21602
The smtplib.py also has the same problem.
The EINTR cannot be handled properly.
meishao commentedon May 29, 2014
@neologix,
May I attach the patch file of smtplib.py for review?
florentx commentedon May 29, 2014
@meishao
Previous comments answer your question :
http://bugs.python.org/issue20611#msg218836
http://bugs.python.org/issue20611#msg218841
meishao commentedon May 29, 2014
@flox
Thank you for your comment.
So we just only modify the socket.py to handle the system level call, is it right?
Please let me attach the patch file of socket.py for 2.7.2.
tholzer commentedon May 29, 2014
Oops, I missed a break statement at the end of socket_2.7.3_eintr_patch.py. I've fixed this now in the attached patch.
@meishao
Could you please also update your socket_2_7_2_patch.py and add the missing break statement ?
meishao commentedon May 30, 2014
@tholzer
I've updated socket_2_7_2_patch.py and added the missing break statement.
tholzer commentedon May 30, 2014
And a test case for smtplib:
Fails with:
socket.error: [Errno 4] Interrupted system call
gpshead commentedon Jun 3, 2014
Something like the patch i'm attaching to socketmodule.c is what I would prefer. I haven't looked at or tried tests for it yet.
vstinner commentedon Jul 24, 2014
The issue is just an example of the main issue bpo-18885 which proposes to retry interrupted syscalls. I hesitate to mark it as duplicate, but it contains an interesting patch.
vadmium commentedon Feb 8, 2015
See also PEP-475 and bpo-23285 for the general fix in Python 3
vstinner commentedon Apr 6, 2015
This issue was fixed in Python 3.5 as part of the PEP-475: see issue bpo-23618 which modified socket.socket.connect() to handle EINTR. It's not as simple as retrying connect() in a loop. You must respect the socket timeout (it's better to have a monotonic clock here, it's now always the case in Python 3.5). When connect() returns EINTR, the connection runs asynchronously, you have to call select() to wait until the connection completes or fails. Then you have to call getsockopt() to get the socket error code.
In Python 3.5, socket.socket.connect() still raises InterruptedError if the socket is non-blocking:
https://docs.python.org/dev/library/socket.html#socket.socket.connect
bpo-20611-connect-eintr-gps01.diff calls again connect() if connect() failed with EINTR. According to the issue bpo-23618, it might work on some platforms, but it's not portable.
For Python 2.7 and 3.4, instead of fixing socket.socket.connect(), which requires complex code, we may only workaround the issue in create_connection(). If connect() raises OSError(EINTR), drop the socket and retry with a fresh connection in a loop until the connection completes or raises a different exception. (And do that for each address.)
gpshead commentedon Apr 7, 2015
i'm moving this to the more recent issue as i like the patch in that one better.