Skip to content

Commit 7ea579e

Browse files
committed
DISPATCH-1962 Fix leak of IoAdapter_init
1 parent c6ea12e commit 7ea579e

File tree

6 files changed

+31
-14
lines changed

6 files changed

+31
-14
lines changed

src/dispatch.c

+1
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ qd_error_t qd_dispatch_prepare(qd_dispatch_t *qd)
338338
void qd_dispatch_set_agent(qd_dispatch_t *qd, void *agent) {
339339
assert(agent);
340340
assert(!qd->agent);
341+
Py_IncRef(agent);
341342
qd->agent = agent;
342343
}
343344

src/python_embedded.c

+21-5
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,8 @@ static PyTypeObject LogAdapterType = {
564564
.tp_dealloc = (destructor)LogAdapter_dealloc,
565565
.tp_flags = Py_TPFLAGS_DEFAULT,
566566
.tp_methods = LogAdapter_methods,
567-
.tp_init = (initproc)LogAdapter_init
567+
.tp_init = (initproc)LogAdapter_init,
568+
.tp_new = PyType_GenericNew,
568569
};
569570

570571

@@ -718,10 +719,24 @@ static int IoAdapter_init(IoAdapter *self, PyObject *args, PyObject *kwds)
718719
return 0;
719720
}
720721

722+
// visit all members which may conceivably participate in reference cycles
723+
static int IoAdapter_traverse(IoAdapter* self, visitproc visit, void *arg)
724+
{
725+
Py_VISIT(self->handler);
726+
return 0;
727+
}
728+
729+
static int IoAdapter_clear(IoAdapter* self)
730+
{
731+
Py_CLEAR(self->handler);
732+
return 0;
733+
}
734+
721735
static void IoAdapter_dealloc(IoAdapter* self)
722736
{
723737
qdr_core_unsubscribe(self->sub);
724-
Py_DECREF(self->handler);
738+
PyObject_GC_UnTrack(self);
739+
IoAdapter_clear(self);
725740
Py_TYPE(self)->tp_free((PyObject*)self);
726741
}
727742

@@ -814,10 +829,13 @@ static PyTypeObject IoAdapterType = {
814829
.tp_name = DISPATCH_MODULE ".IoAdapter",
815830
.tp_doc = "Dispatch IO Adapter",
816831
.tp_basicsize = sizeof(IoAdapter),
832+
.tp_traverse = (traverseproc)IoAdapter_traverse,
833+
.tp_clear = (inquiry)IoAdapter_clear,
817834
.tp_dealloc = (destructor)IoAdapter_dealloc,
818-
.tp_flags = Py_TPFLAGS_DEFAULT,
835+
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
819836
.tp_methods = IoAdapter_methods,
820837
.tp_init = (initproc)IoAdapter_init,
838+
.tp_new = PyType_GenericNew,
821839
};
822840

823841

@@ -833,8 +851,6 @@ static void qd_register_constant(PyObject *module, const char *name, uint32_t va
833851

834852
static void qd_python_setup(void)
835853
{
836-
LogAdapterType.tp_new = PyType_GenericNew;
837-
IoAdapterType.tp_new = PyType_GenericNew;
838854
if ((PyType_Ready(&LogAdapterType) < 0) || (PyType_Ready(&IoAdapterType) < 0)) {
839855
qd_error_py();
840856
qd_log(log_source, QD_LOG_CRITICAL, "Unable to initialize Adapters");

src/router_node.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -2141,12 +2141,12 @@ void qd_router_free(qd_router_t *router)
21412141

21422142
qd_container_set_default_node_type(router->qd, 0, 0, QD_DIST_BOTH);
21432143

2144+
qd_router_python_free(router);
21442145
qdr_core_free(router->router_core);
21452146
qd_tracemask_free(router->tracemask);
21462147
qd_timer_free(router->timer);
21472148
sys_mutex_free(router->lock);
21482149
qd_router_configure_free(router);
2149-
qd_router_python_free(router);
21502150

21512151
free(router);
21522152
free(node_id);

src/router_pynode.c

+7-1
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,7 @@ qd_error_t qd_router_python_setup(qd_router_t *router)
444444
// Instantiate the router
445445
//
446446
pyRouter = PyObject_CallObject(pClass, pArgs);
447+
Py_DECREF(pClass);
447448
Py_DECREF(pArgs);
448449
Py_DECREF(adapterType);
449450
QD_ERROR_PY_RET();
@@ -456,7 +457,12 @@ qd_error_t qd_router_python_setup(qd_router_t *router)
456457
}
457458

458459
void qd_router_python_free(qd_router_t *router) {
459-
// empty
460+
Py_XDECREF(pyRouter);
461+
Py_XDECREF(pyTick);
462+
Py_XDECREF(pySetMobileSeq);
463+
Py_XDECREF(pySetMyMobileSeq);
464+
Py_XDECREF(pyLinkLost);
465+
PyGC_Collect();
460466
}
461467

462468

tests/core_timer_test.c

+1
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ static char* test_core_timer(void *context)
170170
//
171171
for (long i = 0; i < 5; i++)
172172
qdr_core_timer_free_CT(core, timers[i]);
173+
free(core);
173174

174175
return 0;
175176
}

tests/lsan.supp

-7
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ leak:qdr_error_description
1313
# to be triaged; unit_tests
1414
leak:http-libwebsockets.c
1515

16-
# to be triaged; pretty much all tests
17-
leak:^IoAdapter_init$
18-
1916
# to be triaged; system_tests_http
2017
leak:^callback_healthz$
2118
leak:^callback_metrics$
@@ -34,10 +31,6 @@ leak:run_unit_tests.c
3431
# DISPATCH-1844 - shutdown leak
3532
leak:sys_mutex
3633

37-
# expected, not a bug:
38-
#
39-
leak:qdr_core_subscribe
40-
4134
# Ubuntu 16.04 (Xenial)
4235
#
4336
leak:_ctypes_alloc_format_string

0 commit comments

Comments
 (0)