From: Witold Kręcicki Date: Mon, 20 Jan 2020 11:12:29 +0000 (+0100) Subject: Unit test for the taskmgr pause/unpause race X-Git-Tag: v9.16.0~56^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1beba0fa59e8d905472be85981c8e329d6da001b;p=thirdparty%2Fbind9.git Unit test for the taskmgr pause/unpause race --- diff --git a/lib/isc/tests/task_test.c b/lib/isc/tests/task_test.c index d44aee5898b..c7093a69670 100644 --- a/lib/isc/tests/task_test.c +++ b/lib/isc/tests/task_test.c @@ -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;