diff --git a/CHANGES b/CHANGES index 9372712159..fad0b2354d 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,9 @@ 3574. [doc] The 'hostname' keyword was missing from server-id description in the named.conf man page. [RT #33476] +3571. [bug] Address race condition in dns_client_startresolve(). + [RT #33234] + --- 9.9.3 released --- 3568. [cleanup] Add a product description line to the version file, diff --git a/lib/dns/client.c b/lib/dns/client.c index fc551cf9df..e9e8bde28c 100644 --- a/lib/dns/client.c +++ b/lib/dns/client.c @@ -1094,11 +1094,23 @@ client_resfind(resctx_t *rctx, dns_fetchevent_t *event) { UNLOCK(&rctx->lock); } + +static void +suspend(isc_task_t *task, isc_event_t *event) { + isc_appctx_t *actx = event->ev_arg; + + UNUSED(task); + + isc_app_ctxsuspend(actx); + isc_event_free(&event); +} + static void resolve_done(isc_task_t *task, isc_event_t *event) { resarg_t *resarg = event->ev_arg; dns_clientresevent_t *rev = (dns_clientresevent_t *)event; dns_name_t *name; + isc_result_t result; UNUSED(task); @@ -1117,8 +1129,16 @@ resolve_done(isc_task_t *task, isc_event_t *event) { if (!resarg->canceled) { UNLOCK(&resarg->lock); - /* Exit from the internal event loop */ - isc_app_ctxsuspend(resarg->actx); + /* + * We may or may not be running. isc__appctx_onrun will + * fail if we are currently running otherwise we post a + * action to call isc_app_ctxsuspend when we do start + * running. + */ + result = isc_app_ctxonrun(resarg->actx, resarg->client->mctx, + task, suspend, resarg->actx); + if (result == ISC_R_ALREADYRUNNING) + isc_app_ctxsuspend(resarg->actx); } else { /* * We have already exited from the loop (due to some @@ -1310,9 +1330,8 @@ dns_client_startresolve(dns_client_t *client, dns_name_t *name, ISC_LIST_APPEND(client->resctxs, rctx, link); UNLOCK(&client->lock); - client_resfind(rctx, NULL); - *transp = (dns_clientrestrans_t *)rctx; + client_resfind(rctx, NULL); return (ISC_R_SUCCESS); diff --git a/lib/isc/app_api.c b/lib/isc/app_api.c index ce767d1750..b46fe03036 100644 --- a/lib/isc/app_api.c +++ b/lib/isc/app_api.c @@ -90,6 +90,16 @@ isc_app_ctxrun(isc_appctx_t *ctx) { return (ctx->methods->ctxrun(ctx)); } +isc_result_t +isc_app_ctxonrun(isc_appctx_t *ctx, isc_mem_t *mctx, + isc_task_t *task, isc_taskaction_t action, + void *arg) +{ + REQUIRE(ISCAPI_APPCTX_VALID(ctx)); + + return (ctx->methods->ctxonrun(ctx, mctx, task, action, arg)); +} + isc_result_t isc_app_ctxsuspend(isc_appctx_t *ctx) { REQUIRE(ISCAPI_APPCTX_VALID(ctx)); diff --git a/lib/isc/include/isc/app.h b/lib/isc/include/isc/app.h index e0be790637..239436b8c4 100644 --- a/lib/isc/include/isc/app.h +++ b/lib/isc/include/isc/app.h @@ -117,6 +117,9 @@ typedef struct isc_appmethods { isc_socketmgr_t *timermgr); void (*settimermgr)(isc_appctx_t *ctx, isc_timermgr_t *timermgr); + isc_result_t (*ctxonrun)(isc_appctx_t *ctx, isc_mem_t *mctx, + isc_task_t *task, isc_taskaction_t action, + void *arg); } isc_appmethods_t; /*% @@ -153,10 +156,13 @@ isc_app_start(void); * close to the beginning of the application as possible. * * Requires: - * 'ctx' is a valid application context (for app_ctxstart()). + *\li 'ctx' is a valid application context (for app_ctxstart()). */ isc_result_t +isc_app_ctxonrun(isc_appctx_t *ctx, isc_mem_t *mctx, isc_task_t *task, + isc_taskaction_t action, void *arg); +isc_result_t isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action, void *arg); /*!< @@ -164,6 +170,7 @@ isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action, * * Requires: *\li isc_app_start() has been called. + *\li 'ctx' is a valid application context (for app_ctxonrun()). * * Returns: * ISC_R_SUCCESS diff --git a/lib/isc/unix/app.c b/lib/isc/unix/app.c index 5393be9425..69b4d4b8e1 100644 --- a/lib/isc/unix/app.c +++ b/lib/isc/unix/app.c @@ -107,6 +107,11 @@ ISC_APPFUNC_SCOPE void isc__appctx_setsocketmgr(isc_appctx_t *ctx, isc_socketmgr_t *socketmgr); ISC_APPFUNC_SCOPE void isc__appctx_settimermgr(isc_appctx_t *ctx, isc_timermgr_t *timermgr); +ISC_APPFUNC_SCOPE isc_result_t isc__app_ctxonrun(isc_appctx_t *ctx, + isc_mem_t *mctx, + isc_task_t *task, + isc_taskaction_t action, + void *arg); /* * The application context of this module. This implementation actually @@ -148,8 +153,7 @@ static struct { * The following are defined just for avoiding unused static functions. */ #ifndef BIND9 - void *run, *shutdown, *start, *onrun, *reload, *finish, - *block, *unblock; + void *run, *shutdown, *start, *reload, *finish, *block, *unblock; #endif } appmethods = { { @@ -161,7 +165,8 @@ static struct { isc__app_ctxfinish, isc__appctx_settaskmgr, isc__appctx_setsocketmgr, - isc__appctx_settimermgr + isc__appctx_settimermgr, + isc__app_ctxonrun } #ifndef BIND9 , @@ -387,13 +392,22 @@ ISC_APPFUNC_SCOPE isc_result_t isc__app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action, void *arg) { + return (isc__app_ctxonrun((isc_appctx_t *)&isc_g_appctx, mctx, + task, action, arg)); +} + +isc_result_t +isc__app_ctxonrun(isc_appctx_t *ctx0, isc_mem_t *mctx, isc_task_t *task, + isc_taskaction_t action, void *arg) +{ + isc__appctx_t *ctx = (isc__appctx_t *)ctx0; isc_event_t *event; isc_task_t *cloned_task = NULL; isc_result_t result; - LOCK(&isc_g_appctx.lock); + LOCK(&ctx->lock); - if (isc_g_appctx.running) { + if (ctx->running) { result = ISC_R_ALREADYRUNNING; goto unlock; } @@ -410,12 +424,12 @@ isc__app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action, goto unlock; } - ISC_LIST_APPEND(isc_g_appctx.on_run, event, ev_link); + ISC_LIST_APPEND(ctx->on_run, event, ev_link); result = ISC_R_SUCCESS; unlock: - UNLOCK(&isc_g_appctx.lock); + UNLOCK(&ctx->lock); return (result); }