Bug 1331

Summary: libunbound segfault in threaded mode when context is deleted
Product: unbound Reporter: Andrew Tunnell-Jones <andrew>
Component: serverAssignee: unbound team <unbound-team>
Status: RESOLVED FIXED    
Severity: normal CC: cathya, wouter
Priority: P5    
Version: 1.6.4   
Hardware: Other   
OS: All   

Description Andrew Tunnell-Jones 2017-07-03 13:31:14 CEST
Hi,

If I create a context, set async to true, start an asynchronous resolve and then delete the context I seem to be able to reliably raise a segfault.

    #include <unbound.h>

    static void callback(void* arg, int err, struct ub_result* result) {}

    int main(void) {
        struct ub_ctx* ctx = ub_ctx_create();
        ub_ctx_async(ctx, 1);
        ub_resolve_async(ctx, "example.com.", 1, 1, 0, callback, 0);
        ub_ctx_delete(ctx);
    }

I get the same result on macOS with 1.6.4 and Debian with 1.4.22. On the Mac, if I insert a ten second sleep before calling ub_ctx_delete no segfault occurs. I haven't tried that on Debian. Both machines are wimpy, the Mac is a dual-core with hyper-threading and the Debian machine is a $3 single-core VPS.

Look forward to your advice,

Andrew
Comment 1 Wouter Wijngaards 2017-07-03 13:45:46 CEST
Hi Andrew,

Thank you for the bug report.  I have fixed the bug.  The fix is in the code repository, but the patch is also here should you want it.

Best regards, Wouter

Index: libunbound/libworker.c
===================================================================
--- libunbound/libworker.c	(revision 4256)
+++ libunbound/libworker.c	(working copy)
@@ -749,7 +749,7 @@
 {
 	struct ctx_query* q = (struct ctx_query*)arg;
 
-	if(q->cancelled) {
+	if(q->cancelled || q->w->back->want_to_quit) {
 		if(q->w->is_bg_thread) {
 			/* delete it now */
 			struct ub_ctx* ctx = q->w->ctx;