Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Program aborted with [Errno 4] Interrupted system call #8

Open
motoz opened this issue Mar 17, 2016 · 4 comments
Open

Program aborted with [Errno 4] Interrupted system call #8

motoz opened this issue Mar 17, 2016 · 4 comments

Comments

@motoz
Copy link

motoz commented Mar 17, 2016

I'm using a periodic signal handler in my program and bumped into this with another socket connection. Then it occured to me that this could be the cause of the occasional errors I have seen from the pyownet communication.

This short program shows the issue:

from pyownet import protocol
import signal, time

def periodic_signal_handler(signum, frame):
    print 'sig'

signal.signal(signal.SIGALRM, periodic_signal_handler)
signal.setitimer(signal.ITIMER_REAL, 2, 0.01)
p = protocol.proxy('192.168.1.7')

while True:
    p.dir()
    time.sleep(0.2)

typical output:

python errnotest.py 
sig
sig
sig
sig
sig
sig
sig
sig
Traceback (most recent call last):
  File "errnotest.py", line 14, in <module>
    p.dir()
  File "/usr/local/lib/python2.7/dist-packages/pyownet/protocol.py", line 500, in dir
    ret, data = self.sendmess(msg, str2bytez(path), flags)
  File "/usr/local/lib/python2.7/dist-packages/pyownet/protocol.py", line 467, in sendmess
    raise ConnError(*err.args)
pyownet.protocol.ConnError: [Errno 4] Interrupted system call

Some background info I found:
http://stackoverflow.com/questions/16094618/python-socket-recv-and-signals
http://250bpm.com/blog:12

Seems like python does not reastart the syscall on EINTR even though it should, so it has to be handled in the program by looping on the syscall until it ends with something other than EINTR:

while True:
    try:
        data = s.recv(2048)
    except socket.error, e:
        if e.errno != errno.EINTR:
            raise
    else:
        break

(Ubuntu 14.04 with python 2.7.6)

@miccoli
Copy link
Owner

miccoli commented Mar 17, 2016

This issue is linked to a python "feature" described in PEP 0475. Fortunately this "feature" was declared a bug and corrected in Python 3.5

I plan to keep full support for Python 2.7, so I will fix this issue, but I still have to set a milestone linked to better python version handling.

@miccoli miccoli added the bug label Mar 17, 2016
@miccoli
Copy link
Owner

miccoli commented Mar 17, 2016

Bug confirmed for pyownet ver. 0.9.0 and 0.9.1.dev7 on CPython 2.7.11; bug absent, as expected, on CPython 3.5.1.

miccoli added a commit that referenced this issue Mar 17, 2016
@miccoli
Copy link
Owner

miccoli commented Mar 26, 2016

A quick update on this issue.

Unfortunately Python 2.7.11 and Python 3.5.1 have diverged enough to make it unpractical to fix this issue within a Python 2-3 compatible code. Since I've already in my pipeline the complete rewriting of the socket code, solving this issue will not happen really soon now.

For Python2 at present the only possible mitigation is retrying the operation at the application level.

import errno
from pyownet import protocol

owp = protocol.proxy()
while True:
    try:
        res = owp.dir()
        break
    except protocol.ConnError as cerr:
        if cerr.errno == errno.EINTR:
            continue

@miccoli miccoli added this to the rewrite low level socket code milestone Mar 26, 2016
@motoz
Copy link
Author

motoz commented Mar 26, 2016

Retrying at the application level is fine with me, and one more reason to begin porting to python 3 then.

miccoli added a commit that referenced this issue Mar 28, 2016
(this makes the bug a feature ;-)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants