mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-20 20:06:12 +00:00
IPyKernel signal and poll
This commit is contained in:
parent
926a9ffd1e
commit
693fc1eb1f
@ -7,8 +7,8 @@ from ipykernel.ipkernel import IPythonKernel
|
|||||||
|
|
||||||
# TODO: Make this behave like a Popen instance and pipe it to IPyKernelInterfaceJupyter!
|
# TODO: Make this behave like a Popen instance and pipe it to IPyKernelInterfaceJupyter!
|
||||||
class IPyKernelInterfaceKernel:
|
class IPyKernelInterfaceKernel:
|
||||||
def kill(self):
|
def send_signal(self, signum):
|
||||||
print("No!! Not into the pit! It burns!!!")
|
pass
|
||||||
|
|
||||||
def poll(self):
|
def poll(self):
|
||||||
return None
|
return None
|
||||||
|
@ -1,34 +1,32 @@
|
|||||||
|
|
||||||
from jupyter_client.ioloop import IOLoopKernelManager
|
from jupyter_client.ioloop import IOLoopKernelManager
|
||||||
from notebook.notebookapp import *
|
from notebook.notebookapp import *
|
||||||
|
import signal
|
||||||
|
import cutter_internal
|
||||||
|
|
||||||
|
|
||||||
# TODO: this must behave like a Popen instance and pipe to IPyKernelInterfaceKernel!
|
|
||||||
class IPyKernelInterfaceJupyter:
|
class IPyKernelInterfaceJupyter:
|
||||||
def __init__(self, id):
|
def __init__(self, id):
|
||||||
self._id = id
|
self._id = id
|
||||||
|
|
||||||
|
def send_signal(self, signum):
|
||||||
|
cutter_internal.kernel_interface_send_signal(self._id, signum)
|
||||||
|
|
||||||
def kill(self):
|
def kill(self):
|
||||||
print("DIE!! " + str(self._id))
|
self.send_signal(signal.SIGKILL)
|
||||||
|
|
||||||
|
def terminate(self):
|
||||||
|
self.send_signal(signal.SIGTERM)
|
||||||
|
|
||||||
def poll(self):
|
def poll(self):
|
||||||
return None
|
return cutter_internal.kernel_interface_poll(self._id)
|
||||||
|
|
||||||
|
def wait(self, timeout=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class CutterInternalIPyKernelManager(IOLoopKernelManager):
|
class CutterInternalIPyKernelManager(IOLoopKernelManager):
|
||||||
def start_kernel(self, **kw):
|
def start_kernel(self, **kw):
|
||||||
"""Starts a kernel on this host in a separate process.
|
|
||||||
|
|
||||||
If random ports (port=0) are being used, this method must be called
|
|
||||||
before the channels are created.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
`**kw` : optional
|
|
||||||
keyword arguments that are passed down to build the kernel_cmd
|
|
||||||
and launching the kernel (e.g. Popen kwargs).
|
|
||||||
"""
|
|
||||||
|
|
||||||
# write connection file / get default ports
|
# write connection file / get default ports
|
||||||
self.write_connection_file()
|
self.write_connection_file()
|
||||||
|
|
||||||
@ -50,15 +48,16 @@ class CutterInternalIPyKernelManager(IOLoopKernelManager):
|
|||||||
self.log.debug("Starting kernel: %s", kernel_cmd)
|
self.log.debug("Starting kernel: %s", kernel_cmd)
|
||||||
|
|
||||||
# TODO: kernel_cmd including python executable and so on is currently used for argv. Make a clean version!
|
# TODO: kernel_cmd including python executable and so on is currently used for argv. Make a clean version!
|
||||||
import cutter_internal
|
|
||||||
id = cutter_internal.launch_ipykernel(kernel_cmd, env=env, **kw)
|
id = cutter_internal.launch_ipykernel(kernel_cmd, env=env, **kw)
|
||||||
self.kernel = IPyKernelInterfaceJupyter(id)
|
self.kernel = IPyKernelInterfaceJupyter(id)
|
||||||
# self._launch_kernel(kernel_cmd, env=env,
|
# self._launch_kernel(kernel_cmd, env=env, **kw)
|
||||||
# **kw)
|
|
||||||
|
|
||||||
self.start_restarter()
|
self.start_restarter()
|
||||||
self._connect_control_socket()
|
self._connect_control_socket()
|
||||||
|
|
||||||
|
def signal_kernel(self, signum):
|
||||||
|
self.kernel.send_signal(signum)
|
||||||
|
|
||||||
|
|
||||||
def kernel_manager_factory(kernel_name, **kwargs):
|
def kernel_manager_factory(kernel_name, **kwargs):
|
||||||
if kernel_name in {"python", "python2", "python3"}:
|
if kernel_name in {"python", "python2", "python3"}:
|
||||||
|
@ -144,5 +144,10 @@ long JupyterConnection::startNestedIPyKernel(const QStringList &argv)
|
|||||||
|
|
||||||
NestedIPyKernel *JupyterConnection::getNestedIPyKernel(long id)
|
NestedIPyKernel *JupyterConnection::getNestedIPyKernel(long id)
|
||||||
{
|
{
|
||||||
return kernels[id];
|
auto it = kernels.find(id);
|
||||||
|
if(it == kernels.end())
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return *it;
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,8 @@ NestedIPyKernel *NestedIPyKernel::start(const QStringList &argv)
|
|||||||
|
|
||||||
NestedIPyKernel::NestedIPyKernel(PyObject *cutterIPykernelModule, const QStringList &argv)
|
NestedIPyKernel::NestedIPyKernel(PyObject *cutterIPykernelModule, const QStringList &argv)
|
||||||
{
|
{
|
||||||
|
threadState = PyThreadState_Get();
|
||||||
|
|
||||||
auto launchFunc = PyObject_GetAttrString(cutterIPykernelModule, "launch_ipykernel");
|
auto launchFunc = PyObject_GetAttrString(cutterIPykernelModule, "launch_ipykernel");
|
||||||
|
|
||||||
PyObject *argvListObject = PyList_New(argv.size());
|
PyObject *argvListObject = PyList_New(argv.size());
|
||||||
@ -59,12 +61,24 @@ NestedIPyKernel::NestedIPyKernel(PyObject *cutterIPykernelModule, const QStringL
|
|||||||
|
|
||||||
NestedIPyKernel::~NestedIPyKernel()
|
NestedIPyKernel::~NestedIPyKernel()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NestedIPyKernel::kill()
|
void NestedIPyKernel::sendSignal(long signum)
|
||||||
{
|
{
|
||||||
auto parentThreadState = PyThreadState_Swap(threadState);
|
auto parentThreadState = PyThreadState_Swap(threadState);
|
||||||
PyObject_CallMethod(kernel, "kill", nullptr);
|
PyObject_CallMethod(kernel, "send_signal", "l", signum);
|
||||||
PyThreadState_Swap(parentThreadState);
|
PyThreadState_Swap(parentThreadState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVariant NestedIPyKernel::poll()
|
||||||
|
{
|
||||||
|
QVariant ret;
|
||||||
|
auto parentThreadState = PyThreadState_Swap(threadState);
|
||||||
|
PyObject *pyRet = PyObject_CallMethod(kernel, "poll", nullptr);
|
||||||
|
if(PyLong_Check(pyRet))
|
||||||
|
{
|
||||||
|
ret = (qlonglong)PyLong_AsLong(pyRet);
|
||||||
|
}
|
||||||
|
PyThreadState_Swap(parentThreadState);
|
||||||
|
return ret;
|
||||||
|
}
|
@ -17,7 +17,8 @@ public:
|
|||||||
static NestedIPyKernel *start(const QStringList &argv);
|
static NestedIPyKernel *start(const QStringList &argv);
|
||||||
~NestedIPyKernel();
|
~NestedIPyKernel();
|
||||||
|
|
||||||
void kill();
|
void sendSignal(long signum);
|
||||||
|
QVariant poll();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NestedIPyKernel(PyObject *cutterIPykernelModule, const QStringList &argv);
|
NestedIPyKernel(PyObject *cutterIPykernelModule, const QStringList &argv);
|
||||||
|
@ -74,25 +74,60 @@ PyObject *api_internal_launch_ipykernel(PyObject *self, PyObject *args, PyObject
|
|||||||
return PyLong_FromLong(id);
|
return PyLong_FromLong(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *api_internal_kernel_interface_kill(PyObject *, PyObject *args)
|
PyObject *api_internal_kernel_interface_send_signal(PyObject *, PyObject *args)
|
||||||
|
{
|
||||||
|
long id;
|
||||||
|
long signum;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "ll", &id, &signum))
|
||||||
|
{
|
||||||
|
qWarning() << "Invalid args passed to api_internal_kernel_interface_send_signal().";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
NestedIPyKernel *kernel = Jupyter()->getNestedIPyKernel(id);
|
||||||
|
if(kernel)
|
||||||
|
{
|
||||||
|
kernel->sendSignal(signum);
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *api_internal_kernel_interface_poll(PyObject *, PyObject *args)
|
||||||
{
|
{
|
||||||
long id;
|
long id;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "l", &id))
|
if (!PyArg_ParseTuple(args, "l", &id))
|
||||||
{
|
{
|
||||||
qWarning() << "Invalid args passed to api_internal_kernel_interface_kill().";
|
qWarning() << "Invalid args passed to api_internal_kernel_interface_poll().";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Jupyter()->getNestedIPyKernel(id)->kill();
|
NestedIPyKernel *kernel = Jupyter()->getNestedIPyKernel(id);
|
||||||
|
if(!kernel)
|
||||||
|
{
|
||||||
|
return PyLong_FromLong(0);
|
||||||
|
}
|
||||||
|
|
||||||
Py_RETURN_NONE;
|
QVariant v = kernel->poll();
|
||||||
|
bool ok;
|
||||||
|
auto ret = static_cast<long>(v.toLongLong(&ok));
|
||||||
|
if(ok)
|
||||||
|
{
|
||||||
|
return PyLong_FromLong(ret);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PyMethodDef CutterInternalMethods[] = {
|
PyMethodDef CutterInternalMethods[] = {
|
||||||
{"launch_ipykernel", (PyCFunction)api_internal_launch_ipykernel, METH_VARARGS | METH_KEYWORDS,
|
{"launch_ipykernel", (PyCFunction)api_internal_launch_ipykernel, METH_VARARGS | METH_KEYWORDS,
|
||||||
"Launch an IPython Kernel in a subinterpreter"},
|
"Launch an IPython Kernel in a subinterpreter"},
|
||||||
{"kernel_interface_kill", (PyCFunction)api_internal_kernel_interface_kill, METH_VARARGS, ""},
|
{"kernel_interface_send_signal", (PyCFunction)api_internal_kernel_interface_send_signal, METH_VARARGS, ""},
|
||||||
|
{"kernel_interface_poll", (PyCFunction)api_internal_kernel_interface_poll, METH_VARARGS, ""},
|
||||||
{NULL, NULL, 0, NULL}
|
{NULL, NULL, 0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user