]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Unit test for the taskmgr pause/unpause race
authorWitold Kręcicki <wpk@isc.org>
Mon, 20 Jan 2020 11:12:29 +0000 (12:12 +0100)
committerWitold Kręcicki <wpk@isc.org>
Tue, 21 Jan 2020 09:06:19 +0000 (10:06 +0100)
lib/isc/tests/task_test.c

index d44aee5898b4c7c07bb51b4f87d19492e2f865da..c7093a696708557f54d0425ea566d573487fcc3c 100644 (file)
@@ -48,7 +48,7 @@ static isc_condition_t cv;
 
 atomic_int_fast32_t counter;
 static int active[10];
-static atomic_bool done;
+static atomic_bool done, done2;
 
 static int
 _setup(void **state) {
@@ -429,6 +429,83 @@ privilege_drop(void **state) {
        assert_null(task2);
 }
 
+static void
+sleep_cb(isc_task_t *task, isc_event_t *event) {
+       UNUSED(task);
+       int p = *(int*)event->ev_arg;
+       if (p == 1) {
+               /*
+                * Signal the main thread that we're running, so that
+                * it can trigger the race.
+                */
+               LOCK(&lock);
+               atomic_store(&done2, true);
+               SIGNAL(&cv);
+               UNLOCK(&lock);
+               /*
+                * Wait for the operations in the main thread to be finished.
+                */
+               LOCK(&lock);
+               while (!atomic_load(&done)) {
+                       WAIT(&cv, &lock);
+               }
+               UNLOCK(&lock);
+       } else {
+               /*
+                * Wait for the operations in the main thread to be finished.
+                */
+               LOCK(&lock);
+               atomic_store(&done2, true);
+               SIGNAL(&cv);
+               UNLOCK(&lock);
+       }
+       isc_event_free(&event);
+}
+
+static void
+pause_unpause(void **state) {
+       isc_result_t result;
+       isc_task_t *task = NULL;
+       isc_event_t *event1,*event2 = NULL;
+       UNUSED(state);
+       atomic_store(&done, false);
+       atomic_store(&done2, false);
+
+       result = isc_task_create(taskmgr, 0, &task);
+       assert_int_equal(result, ISC_R_SUCCESS);
+
+       event1 = isc_event_allocate(test_mctx, task, ISC_TASKEVENT_TEST,
+                                   sleep_cb, &(int){1}, sizeof (isc_event_t));
+       assert_non_null(event1);
+       event2 = isc_event_allocate(test_mctx, task, ISC_TASKEVENT_TEST,
+                                   sleep_cb, &(int){2}, sizeof (isc_event_t));
+       assert_non_null(event2);
+       isc_task_send(task, &event1);
+       isc_task_send(task, &event2);
+       /* Wait for event1 to be running */
+       LOCK(&lock);
+       while (!atomic_load(&done2)) {
+               WAIT(&cv, &lock);
+       }
+       UNLOCK(&lock);
+       /* Pause-unpause-detach is what causes the race */
+       isc_task_pause(task);
+       isc_task_unpause(task);
+       isc_task_detach(&task);
+       /* Signal event1 to finish */
+       LOCK(&lock);
+       atomic_store(&done2, false);
+       atomic_store(&done, true);
+       SIGNAL(&cv);
+       UNLOCK(&lock);
+       /* Wait for event2 to finish */
+       LOCK(&lock);
+       while (!atomic_load(&done2)) {
+               WAIT(&cv, &lock);
+       }
+       UNLOCK(&lock);
+}
+
 /*
  * Basic task functions:
  */
@@ -1482,6 +1559,7 @@ main(int argc, char **argv) {
                cmocka_unit_test_setup_teardown(purgeevent, _setup2, _teardown),
                cmocka_unit_test_setup_teardown(purgeevent_notpurge,
                                                _setup, _teardown),
+               cmocka_unit_test_setup_teardown(pause_unpause, _setup, _teardown),
        };
        int c;