]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Destroy reference to taskmgr after all tasks are done
authorOndřej Surý <ondrej@sury.org>
Mon, 10 May 2021 12:11:25 +0000 (14:11 +0200)
committerEvan Hunt <each@isc.org>
Mon, 10 May 2021 19:13:27 +0000 (12:13 -0700)
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

index abdcb56cdd8037f55659e9039ee2515861fe3db4..9225a2284f1f8a54df41bfb9d6a64630621d7213 100644 (file)
@@ -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