From e623c12757b071ecf07696b9d35a7d3668aa7dfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Mon, 10 May 2021 14:11:25 +0200 Subject: [PATCH] Destroy reference to taskmgr after all tasks are done We were clearing the pointer to taskmgr as soon as isc_taskmgr_destroy() would be called and before all tasks were finished. Unfortunately, some tasks would use global named_g_taskmgr objects from inside the events and this would cause either a data race or NULL pointer dereference. This commit fixes the data race by moving the destruction of the referenced pointer to the time after all tasks are finished. --- lib/isc/task.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/lib/isc/task.c b/lib/isc/task.c index abdcb56cdd..9225a2284f 100644 --- a/lib/isc/task.c +++ b/lib/isc/task.c @@ -1074,26 +1074,22 @@ isc__taskmgr_shutdown(isc_taskmgr_t *manager) { void isc__taskmgr_destroy(isc_taskmgr_t **managerp) { REQUIRE(managerp != NULL && VALID_MANAGER(*managerp)); - - isc_taskmgr_t *manager = *managerp; - *managerp = NULL; - XTHREADTRACE("isc_taskmgr_destroy"); #ifdef ISC_TASK_TRACE int counter = 0; - while (isc_refcount_current(&manager->references) > 1 && + while (isc_refcount_current(&(*managerp)->references) > 1 && counter++ < 1000) { usleep(10 * 1000); } + INSIST(counter < 1000); #else - while (isc_refcount_current(&manager->references) > 1) { + while (isc_refcount_current(&(*managerp)->references) > 1) { usleep(10 * 1000); } #endif - REQUIRE(isc_refcount_decrement(&manager->references) == 1); - manager_free(manager); + isc_taskmgr_detach(managerp); } void