Fix IPyKernel restarting

This commit is contained in:
Florian Märkl 2018-02-23 17:42:54 +01:00 committed by xarkes
parent 06dffde0fe
commit b45314fd19
6 changed files with 49 additions and 8 deletions

View File

@ -3,6 +3,7 @@ import logging
import threading
import signal
import cutter_internal
import zmq
from ipykernel.kernelapp import IPKernelApp
from ipykernel.ipkernel import IPythonKernel
@ -28,6 +29,16 @@ class IPyKernelInterfaceKernel:
else:
return 0
def cleanup(self):
self._app.heartbeat.context.destroy()
self._thread.join()
self._app.heartbeat.join()
self._app.iopub_thread.stop()
self._app.kernel.shell.history_manager.save_thread.stop()
zmq.Context.instance().destroy()
# successful if only the main thread remains
return len(threading.enumerate()) == 1
class CutterIPythonKernel(IPythonKernel):
def __init__(self, **kwargs):
@ -59,7 +70,7 @@ def launch_ipykernel(argv):
def run_kernel():
app.kernel_class = CutterIPythonKernel
#app.log_level = logging.DEBUG
# app.log_level = logging.DEBUG
app.initialize(argv[3:])
app.start()

View File

@ -156,3 +156,29 @@ NestedIPyKernel *JupyterConnection::getNestedIPyKernel(long id)
}
return *it;
}
QVariant JupyterConnection::pollNestedIPyKernel(long id)
{
auto it = kernels.find(id);
if(it == kernels.end())
{
return QVariant(0);
}
NestedIPyKernel *kernel = *it;
QVariant v = kernel->poll();
if(!v.isNull())
{
// if poll of kernel returns anything but None, it has already quit and should be cleaned up
PyThreadState *subinterpreterState = kernel->getThreadState();
delete kernel;
kernels.erase(it);
PyThreadState *parentThreadState = PyThreadState_Swap(subinterpreterState);
Py_EndInterpreter(subinterpreterState);
PyThreadState_Swap(parentThreadState);
}
return v;
}

View File

@ -26,6 +26,7 @@ public:
long startNestedIPyKernel(const QStringList &argv);
NestedIPyKernel *getNestedIPyKernel(long id);
QVariant pollNestedIPyKernel(long id);
signals:
void urlReceived(const QString &url);

View File

@ -62,6 +62,13 @@ NestedIPyKernel::NestedIPyKernel(PyObject *cutterIPykernelModule, const QStringL
NestedIPyKernel::~NestedIPyKernel()
{
auto parentThreadState = PyThreadState_Swap(threadState);
auto ret = PyObject_CallMethod(kernel, "cleanup", nullptr);
if (!ret)
{
PyErr_Print();
}
PyThreadState_Swap(parentThreadState);
}
void NestedIPyKernel::sendSignal(long signum)

View File

@ -20,6 +20,8 @@ public:
void sendSignal(long signum);
QVariant poll();
PyThreadState *getThreadState() { return threadState; }
private:
NestedIPyKernel(PyObject *cutterIPykernelModule, const QStringList &argv);

View File

@ -110,13 +110,7 @@ PyObject *api_internal_kernel_interface_poll(PyObject *, PyObject *args)
return nullptr;
}
NestedIPyKernel *kernel = Jupyter()->getNestedIPyKernel(id);
if(!kernel)
{
return PyLong_FromLong(0);
}
QVariant v = kernel->poll();
QVariant v = Jupyter()->pollNestedIPyKernel(id);
bool ok;
auto ret = static_cast<long>(v.toLongLong(&ok));
if(ok)