From 5e6ac36076efbbfbe2c5f1c378a3ff4201058609 Mon Sep 17 00:00:00 2001 From: Wouter Wijngaards Date: Tue, 22 Oct 2013 09:32:10 +0000 Subject: [PATCH] =?UTF-8?q?-=20Patch=20from=20Neel=20Goyal:=20Add=20an=20A?= =?UTF-8?q?PI=20call=20to=20set=20an=20event=20base=20on=20an=20=20=20exis?= =?UTF-8?q?ting=20ub=5Fctx.=20=20This=20basically=20just=20destroys=20the?= =?UTF-8?q?=20current=20worker=20and=20=20=20sets=20the=20event=20base=20t?= =?UTF-8?q?o=20the=20current.=20=20And=20fix=20a=20deadlock=20in=20=20=20u?= =?UTF-8?q?b=5Fresolve=5Fevent=20=E2=80=93=20the=20cfglock=20is=20held=20w?= =?UTF-8?q?hen=20libworker=5Fcreate=20is=20=20=20called.=20=20This=20ends?= =?UTF-8?q?=20up=20trying=20to=20acquire=20the=20lock=20again=20in=20=20?= =?UTF-8?q?=20context=5Fobtain=5Falloc=20in=20the=20call=20chain.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: file:///svn/unbound/trunk@2992 be551aaa-1e26-0410-a405-d3ace91eadb9 --- doc/Changelog | 8 ++++++++ libunbound/libunbound.c | 24 ++++++++++++++++++++++-- libunbound/ubsyms.def | 1 + libunbound/unbound-event.h | 13 +++++++++++-- 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/doc/Changelog b/doc/Changelog index 523f0973a..ff0f765e4 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,11 @@ +22 Oct 2013: Wouter + - Patch from Neel Goyal: Add an API call to set an event base on an + existing ub_ctx. This basically just destroys the current worker and + sets the event base to the current. And fix a deadlock in + ub_resolve_event – the cfglock is held when libworker_create is + called. This ends up trying to acquire the lock again in + context_obtain_alloc in the call chain. + 26 Sep 2013: Wouter - unbound-event.h is installed if configured --with-libevent. It contains low-level library calls, that use libevent's event_base diff --git a/libunbound/libunbound.c b/libunbound/libunbound.c index 847ac1a54..870e37699 100644 --- a/libunbound/libunbound.c +++ b/libunbound/libunbound.c @@ -656,15 +656,14 @@ ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype, return r; } } + lock_basic_unlock(&ctx->cfglock); if(!ctx->event_worker) { ctx->event_worker = libworker_create_event(ctx, ctx->event_base); if(!ctx->event_worker) { - lock_basic_unlock(&ctx->cfglock); return UB_INITFAIL; } } - lock_basic_unlock(&ctx->cfglock); /* create new ctx_query and attempt to add to the list */ q = context_new(ctx, name, rrtype, rrclass, (ub_callback_t)callback, @@ -1212,3 +1211,24 @@ const char* ub_version(void) { return PACKAGE_VERSION; } + +int +ub_ctx_set_event(struct ub_ctx* ctx, struct event_base* base) { + if (!ctx || !ctx->event_base || !base) { + return UB_INITFAIL; + } + if (ctx->event_base == base) { + /* already set */ + return UB_NOERROR; + } + + lock_basic_lock(&ctx->cfglock); + /* destroy the current worker - safe to pass in NULL */ + libworker_delete_event(ctx->event_worker); + ctx->event_worker = NULL; + ctx->event_base = base; + ctx->created_bg = 0; + ctx->dothread = 1; + lock_basic_unlock(&ctx->cfglock); + return UB_NOERROR; +} diff --git a/libunbound/ubsyms.def b/libunbound/ubsyms.def index 26040921b..866c1764c 100644 --- a/libunbound/ubsyms.def +++ b/libunbound/ubsyms.def @@ -29,3 +29,4 @@ ub_ctx_zone_remove ub_ctx_data_add ub_ctx_data_remove ub_version +ub_ctx_set_event diff --git a/libunbound/unbound-event.h b/libunbound/unbound-event.h index 519e4e0de..c49005eec 100644 --- a/libunbound/unbound-event.h +++ b/libunbound/unbound-event.h @@ -63,9 +63,9 @@ extern "C" { struct ub_ctx; struct ub_result; struct event_base; -struct ldns_buffer; +struct ldns_struct_buffer; -typedef void (*ub_event_callback_t)(void*, int, struct ldns_buffer*, int, char*); +typedef void (*ub_event_callback_t)(void*, int, struct ldns_struct_buffer*, int, char*); /** * Create a resolving and validation context. @@ -81,6 +81,15 @@ typedef void (*ub_event_callback_t)(void*, int, struct ldns_buffer*, int, char*) */ struct ub_ctx* ub_ctx_create_event(struct event_base* base); +/** + * Set a new event_base on a context created with ub_ctx_create_event. + * Any outbound queries will be canceled. + * @param ctx the ub_ctx to update. Must have been created with ub_ctx_create_event + * @param base the new event_base to attach to the ctx + * @return 0 if OK, else error + */ +int ub_ctx_set_event(struct ub_ctx* ctx, struct event_base* base); + /** * Perform resolution and validation of the target name. * Asynchronous, after a while, the callback will be called with your