Commit 62f016d5 authored by Mark Andrews's avatar Mark Andrews
Browse files

3571. [bug] Address race condition in dns_client_startresolve().

                        [RT #33234]

Squashed commit of the following:

commit ebfb9f3e783531cc1369bf519eb1c33437ec6f1a
Author: Evan Hunt <each@isc.org>
Date:   Wed May 8 11:47:52 2013 -0700

    [rt33234] style

commit 0a915af759670aadb2455711997d9f29e5c3f794
Author: Mark Andrews <marka@isc.org>
Date:   Wed May 8 18:23:57 2013 +1000

    handle dns_client race
parent 3f97149e
3571. [bug] Address race condition in dns_client_startresolve().
[RT #33234]
3570. [bug] Check internal pointers are valid when loading map
files. [RT #33403]
......
......@@ -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);
......
......@@ -102,6 +102,19 @@ 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));
if (isc_bind9)
return (isc__app_ctxonrun(ctx, mctx, task, action, arg));
return (ctx->methods->ctxonrun(ctx, mctx, task, action, arg));
}
isc_result_t
isc_app_ctxsuspend(isc_appctx_t *ctx) {
REQUIRE(ISCAPI_APPCTX_VALID(ctx));
......
......@@ -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
......
......@@ -92,6 +92,9 @@ void isc__appctx_destroy(isc_appctx_t **ctxp);
void isc__appctx_settaskmgr(isc_appctx_t *ctx, isc_taskmgr_t *taskmgr);
void isc__appctx_setsocketmgr(isc_appctx_t *ctx, isc_socketmgr_t *socketmgr);
void isc__appctx_settimermgr(isc_appctx_t *ctx, isc_timermgr_t *timermgr);
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
......@@ -136,8 +139,7 @@ static struct {
/*%
* The following are defined just for avoiding unused static functions.
*/
void *run, *shutdown, *start, *onrun, *reload, *finish,
*block, *unblock;
void *run, *shutdown, *start, *reload, *finish, *block, *unblock;
} appmethods = {
{
isc__appctx_destroy,
......@@ -148,12 +150,12 @@ static struct {
isc__app_ctxfinish,
isc__appctx_settaskmgr,
isc__appctx_setsocketmgr,
isc__appctx_settimermgr
isc__appctx_settimermgr,
isc__app_ctxonrun
},
(void *)isc__app_run,
(void *)isc__app_shutdown,
(void *)isc__app_start,
(void *)isc__app_onrun,
(void *)isc__app_reload,
(void *)isc__app_finish,
(void *)isc__app_block,
......@@ -398,13 +400,22 @@ 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;
}
......@@ -421,12 +432,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);
}
......@@ -679,7 +690,8 @@ isc__app_ctxrun(isc_appctx_t *ctx0) {
* wait until woken up.
*/
LOCK(&ctx->readylock);
WAIT(&ctx->ready, &ctx->readylock);
if (!ctx->want_reload)
WAIT(&ctx->ready, &ctx->readylock);
UNLOCK(&ctx->readylock);
}
#else /* Don't have sigwait(). */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment