Repository: ipython/ipython

Issue:
"ZMQError: Interrupted system call" from RichIPythonWidget
I've included a RichIPythonWidget in an Qt application I'm working on.  Initially, the IPython kernel starts up and the widget connects and works without problems.  However, when the main program calls QFileDialog my RichIPythonWidget throws an error:
'''
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 551, in __bootstrap_inner self.run()
  File "/usr/local/lib/python2.7/dist-packages/IPython/zmq/heartbeat.py", line 47, in run zmq.device(zmq.FORWARDER, self.socket, self.socket)
  File "device.pyx", line 55, in zmq.core.device.device (zmq/core/device.c:811)
ZMQError: Interrupted system call

Followed by continuous "Kernel process is either remote or unspecified. Cannot restart." messages.
'''
This may be related to #499
I'm using IPython 0.13 and pyzmq 2.2.0.



Discussion:
There's one important difference from #499, in that it's the _kernel_ process that is getting interrupted, rather than the frontend process.  This seems like a problem with the signal handling kernel-side.  Do you have any eventloop integration, or any custom startup code in the Kernel when you see this?

I'm not exactly sure what you are asking, but I think the answer is no.  Here's the widget code I'm using. 

``` python
from IPython.zmq.ipkernel import IPKernelApp
from IPython.lib.kernel import find_connection_file
from IPython.frontend.qt.kernelmanager import QtKernelManager
from IPython.frontend.qt.console.rich_ipython_widget import RichIPythonWidget
from IPython.utils.traitlets import TraitError
from PyQt4 import QtGui, QtCore
import atexit

class IpyConWidget(QtGui.QWidget):
    def __init__(self,  parent=None):     
        QtGui.QWidget.__init__(self,  parent)
        self.kernel_app = IPKernelApp.instance()
        self.kernel_app.initialize(['python', '--pylab=qt'])
        self.kernel_app.kernel.eventloop = self.event_loop(self.kernel_app)
        manager = self.default_manager(self.kernel_app)
        widget = self.console_widget(manager)
        self.vbl = QtGui.QVBoxLayout()
        self.vbl.addWidget(widget)
        self.setLayout(self.vbl)          
        self.kernel_app.start()

    def event_loop(self, kernel):
        kernel.timer = QtCore.QTimer()
        kernel.timer.timeout.connect(kernel.kernel.do_one_iteration)
        kernel.timer.start(1000*kernel.kernel._poll_interval)

    def default_manager(self, kernel):
        connection_file = find_connection_file(kernel.connection_file)
        manager = QtKernelManager(connection_file=connection_file)
        manager.load_connection_file()
        manager.start_channels()
        atexit.register(manager.cleanup_connection_file)
        return manager

    def console_widget(self, manager):
        try: # Ipython v0.13
            widget = RichIPythonWidget(gui_completion='droplist')
        except TraitError:  # IPython v0.12
            widget = RichIPythonWidget(gui_completion=True)
        widget.kernel_manager = manager
        return widget
```

Don't take my word for it but this might help. I'm seeing the same error in notebook intermittently. I can't 100% reproduce it but I found that it correlates with when I try to import Python extensions(probably uninterruptible) which takes a long time to load(seconds) and then try to execute something.

<pre>
Exception in thread Thread-2:
Traceback (most recent call last):
  File "/nfs/data2/babar/software64/lib/python2.7/threading.py", line 551, in __bootstrap_inner
    self.run()
  File "/nfs/data2/babar/software64/lib/python2.7/site-packages/IPython/zmq/heartbeat.py", line 55, in run
    zmq.device(zmq.FORWARDER, self.socket, self.socket)
  File "device.pyx", line 55, in zmq.core.device.device (zmq/core/device.c:854)
ZMQError: Interrupted system call
</pre>

It also seems to correlate with connection speed I'm using. This happens when I work from home through ssh -D proxy but not when I'm school and have gigabit connection to it.

If i try to run an un-interruptable call like tight loop with no C api error checking with in first MappingkernelManager.first_beat second then this always happen. 

Hi, I want to say I have the same error in a different context. In my application, if I try to reload a Cython module and if this triggers recompilation, then I get this exact error. Sadly, even though it is perfectly reproducible in my program, I cannot create a reduced version of the problem. So to reproduce my problem:
 1 - download PyQt-Fit (using pip, from PyPI or from http://code.google.com/p/pyqt-fit/)
 2 - install
 3 - do the following in a ipython qtconsole:

In [1]: import pyqt_fit.kernels 
In [2]: import pyqt_fit._kernels as _k
here, modify the file _kernels.pyx in the pyqt-fit folder
In [3]: reload(_k)
here it should crash the heartbeat, independent from the time it took to compile

Note that if you import pyximport yourself and load pyqt_fit._kernels directly (i.e. not loading pyqt_fit.kernels first), then the error doesn't happen. Also, I only have this problem since I upgrade IPython to 0.13 and even then, it happens only on my linux machine. In short this does'n crash:

In [1]: import pyximport
In [2]: pyximport.install(reload_support=True)
In [3]: import pyqt_fit._kernels as _k
here, modify the file _kernels.pyx in the pyqt-fit folder
In [4]: reload(_k)
here it works just fine

As another data point, I just saw this for the first time in my Qt IPython based app, which uses a RichIPythonWidget:

```
[IPKernelApp] WARNING | Invalid Message:
Traceback (most recent call last):
  File "/home/mspacek/src/ipython/IPython/kernel/zmq/ipkernel.py", line 766, in _raw_input
    ident, reply = self.session.recv(self.stdin_socket, 0)
  File "/home/mspacek/src/ipython/IPython/kernel/zmq/session.py", line 657, in recv
    msg_list = socket.recv_multipart(mode, copy=copy)
  File "/usr/local/lib/python2.7/dist-packages/zmq/sugar/socket.py", line 246, in recv_multipart
    parts = [self.recv(flags, copy=copy, track=track)]
  File "socket.pyx", line 587, in zmq.core.socket.Socket.recv (zmq/core/socket.c:5359)
  File "socket.pyx", line 621, in zmq.core.socket.Socket.recv (zmq/core/socket.c:5178)
  File "socket.pyx", line 130, in zmq.core.socket._recv_copy (zmq/core/socket.c:1690)
  File "checkrc.pxd", line 21, in zmq.core.checkrc._check_rc (zmq/core/socket.c:5838)
ZMQError: Interrupted system call
```

The above was printed in my terminal. The second time it happened, it actually printed within the RichIPythonWidget itself. It may have been a slightly different error. Unfortunately I failed to copy and paste it.

This happened right around when my code running within the app opened a QFileDialog, using getOpenFileName. When creating the dialog, it's set to have no parent. @jt11791 mentions QFileDialog as well, so there may be something to it.

For now, I can't seem to replicate the error. At first, I suspected it had something to do with the user (me) taking a long time to choose the file in the dialog, but I haven't confirmed that. I'm running the latest 1.0.dev from git, and the latest pyzmq installed via pip (13.1.0) on amd64 Xubuntu 12.10, Python 2.7.3


Resolving patch:
diff --git a/IPython/kernel/zmq/heartbeat.py b/IPython/kernel/zmq/heartbeat.py
--- a/IPython/kernel/zmq/heartbeat.py
+++ b/IPython/kernel/zmq/heartbeat.py
@@ -12,6 +12,7 @@
 # Imports
 #-----------------------------------------------------------------------------
 
+import errno
 import os
 import socket
 from threading import Thread
@@ -52,5 +53,13 @@ def run(self):
         self.socket = self.context.socket(zmq.REP)
         c = ':' if self.transport == 'tcp' else '-'
         self.socket.bind('%s://%s' % (self.transport, self.ip) + c + str(self.port))
-        zmq.device(zmq.FORWARDER, self.socket, self.socket)
-
+        while True:
+            try:
+                zmq.device(zmq.FORWARDER, self.socket, self.socket)
+            except zmq.ZMQError as e:
+                if e.errno == errno.EINTR:
+                    continue
+                else:
+                    raise
+            else:
+                break


Test patch: