From faec367cf7b03fb58960f208f54a1e9f5a9bc3eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20Andr=C3=A9=20Vadla=20Ravn=C3=A5s?= Date: Wed, 26 Feb 2020 22:50:41 +0100 Subject: [PATCH] Add Cancellable.get_pollfd() Useful for integrating with an existing event loop. --- frida/core.py | 27 +++++++++++++++++++++++++++ src/_frida.c | 18 ++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/frida/core.py b/frida/core.py index f127c8b..a6d3a42 100644 --- a/frida/core.py +++ b/frida/core.py @@ -448,6 +448,9 @@ class Cancellable(object): def raise_if_cancelled(self): self._impl.raise_if_cancelled() + def get_pollfd(self): + return CancellablePollFD(self._impl) + @classmethod def get_current(cls): return _Cancellable.get_current() @@ -468,6 +471,30 @@ class Cancellable(object): self._impl.cancel() +class CancellablePollFD(object): + def __init__(self, cancellable): + self.handle = cancellable.get_fd() + self._cancellable = cancellable + + def __del__(self): + self.release() + + def release(self): + if self._cancellable is not None: + self._cancellable.release_fd() + self._cancellable = None + self.handle = -1 + + def __repr__(self): + return repr(self.handle) + + def __enter__(self): + return self.handle + + def __exit__(self, *args): + self.release() + + def _to_camel_case(name): result = "" uppercase_next = False diff --git a/src/_frida.c b/src/_frida.c index 9984436..275e09a 100644 --- a/src/_frida.c +++ b/src/_frida.c @@ -375,6 +375,8 @@ static int PyCancellable_init (PyCancellable * self, PyObject * args, PyObject * static PyObject * PyCancellable_repr (PyCancellable * self); static PyObject * PyCancellable_is_cancelled (PyCancellable * self); static PyObject * PyCancellable_raise_if_cancelled (PyCancellable * self); +static PyObject * PyCancellable_get_fd (PyCancellable * self); +static PyObject * PyCancellable_release_fd (PyCancellable * self); static PyObject * PyCancellable_get_current (PyCancellable * self); static PyObject * PyCancellable_push_current (PyCancellable * self); static PyObject * PyCancellable_pop_current (PyCancellable * self); @@ -553,6 +555,8 @@ static PyMethodDef PyCancellable_methods[] = { { "is_cancelled", (PyCFunction) PyCancellable_is_cancelled, METH_NOARGS, "Query whether cancellable has been cancelled." }, { "raise_if_cancelled", (PyCFunction) PyCancellable_raise_if_cancelled, METH_NOARGS, "Raise an exception if cancelled." }, + { "get_fd", (PyCFunction) PyCancellable_get_fd, METH_NOARGS, "Get file descriptor for integrating with an event loop." }, + { "release_fd", (PyCFunction) PyCancellable_release_fd, METH_NOARGS, "Release a resource previously allocated by get_fd()." }, { "get_current", (PyCFunction) PyCancellable_get_current, METH_CLASS | METH_NOARGS, "Get the top cancellable from the stack." }, { "push_current", (PyCFunction) PyCancellable_push_current, METH_NOARGS, "Push cancellable onto the cancellable stack." }, { "pop_current", (PyCFunction) PyCancellable_pop_current, METH_NOARGS, "Pop cancellable off the cancellable stack." }, @@ -3695,6 +3699,20 @@ PyCancellable_raise_if_cancelled (PyCancellable * self) Py_RETURN_NONE; } +static PyObject * +PyCancellable_get_fd (PyCancellable * self) +{ + return PyLong_FromLong (g_cancellable_get_fd (PY_GOBJECT_HANDLE (self))); +} + +static PyObject * +PyCancellable_release_fd (PyCancellable * self) +{ + g_cancellable_release_fd (PY_GOBJECT_HANDLE (self)); + + Py_RETURN_NONE; +} + static PyObject * PyCancellable_get_current (PyCancellable * self) {