Skip to content

Commit 3d15f23

Browse files
committed
perf(event-loop): properly handle Python object reference counts
1 parent bd49d2d commit 3d15f23

1 file changed

Lines changed: 5 additions & 2 deletions

File tree

src/PyEventLoop.cc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
static PyObject *eventLoopJobWrapper(PyObject *jobFn, PyObject *Py_UNUSED(_)) {
99
PyObject *ret = PyObject_CallObject(jobFn, NULL); // jobFn()
1010
Py_XDECREF(ret); // don't care about its return value
11+
Py_XDECREF(jobFn);
1112
PyEventLoop::_locker->decCounter();
1213
if (PyErr_Occurred()) {
1314
return NULL;
@@ -22,8 +23,10 @@ static PyMethodDef loopJobWrapperDef = {"eventLoopJobWrapper", eventLoopJobWrapp
2223
*/
2324
static PyObject *timerJobWrapper(PyObject *jobFn, PyObject *handlerPtr) {
2425
auto handle = (PyEventLoop::AsyncHandle *)PyLong_AsVoidPtr(handlerPtr);
26+
Py_XDECREF(handlerPtr);
2527
PyObject *ret = PyObject_CallObject(jobFn, NULL); // jobFn()
2628
Py_XDECREF(ret); // don't care about its return value
29+
Py_XDECREF(jobFn);
2730
handle->removeRef();
2831
if (PyErr_Occurred()) {
2932
return NULL;
@@ -38,7 +41,7 @@ PyEventLoop::AsyncHandle PyEventLoop::enqueue(PyObject *jobFn) {
3841
PyObject *wrapper = PyCFunction_New(&loopJobWrapperDef, jobFn);
3942
// Enqueue job to the Python event-loop
4043
// https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.call_soon
41-
PyObject *asyncHandle = PyObject_CallMethod(_loop, "call_soon_threadsafe", "O", wrapper); // https://docs.python.org/3/c-api/arg.html#c.Py_BuildValue
44+
PyObject *asyncHandle = PyObject_CallMethod(_loop, "call_soon_threadsafe", "N", wrapper); // https://docs.python.org/3/c-api/arg.html#c.Py_BuildValue
4245
return PyEventLoop::AsyncHandle(asyncHandle);
4346
}
4447

@@ -48,7 +51,7 @@ PyEventLoop::AsyncHandle::id_ptr_pair PyEventLoop::enqueueWithDelay(PyObject *jo
4851
PyObject *handlerPtr = PyLong_FromVoidPtr(handler.second);
4952
// Schedule job to the Python event-loop
5053
// https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.call_later
51-
PyObject *asyncHandle = PyObject_CallMethod(_loop, "call_later", "dOO", delaySeconds, wrapper, handlerPtr); // https://docs.python.org/3/c-api/arg.html#c.Py_BuildValue
54+
PyObject *asyncHandle = PyObject_CallMethod(_loop, "call_later", "dNN", delaySeconds, wrapper, handlerPtr); // https://docs.python.org/3/c-api/arg.html#c.Py_BuildValue
5255
if (asyncHandle == nullptr) {
5356
PyErr_Print(); // RuntimeError: Non-thread-safe operation invoked on an event loop other than the current one
5457
return handler;

0 commit comments

Comments
 (0)