diff --git a/src/context.c b/src/context.c index 8c04bb26..df88d1ad 100644 --- a/src/context.c +++ b/src/context.c @@ -1390,6 +1390,7 @@ getdns_context_create_with_extended_memory_functions( #endif result->processing = 0; result->destroying = 0; + result->to_destroy = 0; result->my_mf.mf_arg = userarg; result->my_mf.mf.ext.malloc = malloc; result->my_mf.mf.ext.realloc = realloc; @@ -1644,6 +1645,10 @@ getdns_context_destroy(struct getdns_context *context) /* If being destroyed during getdns callback, fail via assert */ assert(context->processing == 0); + if (context->processing == 1) { + context->to_destroy = 1; + return; + } if (context->destroying) return; @@ -3768,7 +3773,10 @@ getdns_context_get_num_pending_requests(const getdns_context* context, if (context->outbound_requests.count) context->extension->vmt->run_once(context->extension, 0); - + if (context->to_destroy) { + getdns_context_destroy((getdns_context *)context); + return 0; + } return context->outbound_requests.count; } @@ -3780,6 +3788,8 @@ getdns_context_process_async(getdns_context *context) return GETDNS_RETURN_INVALID_PARAMETER; context->extension->vmt->run_once(context->extension, 0); + if (context->to_destroy) + getdns_context_destroy(context); return GETDNS_RETURN_GOOD; } @@ -3787,6 +3797,8 @@ void getdns_context_run(getdns_context *context) { context->extension->vmt->run(context->extension); + if (context->to_destroy) + getdns_context_destroy(context); } getdns_return_t diff --git a/src/context.h b/src/context.h index 6e7a8960..b24f7c4e 100644 --- a/src/context.h +++ b/src/context.h @@ -397,6 +397,7 @@ struct getdns_context { int processing; int destroying; + int to_destroy; struct mem_funcs mf; struct mem_funcs my_mf; diff --git a/src/test/check_getdns_common.c b/src/test/check_getdns_common.c index 6d0d05a5..38a64526 100644 --- a/src/test/check_getdns_common.c +++ b/src/test/check_getdns_common.c @@ -343,6 +343,7 @@ void assert_ptr_in_answer(struct extracted_response *ex_response) ck_assert_msg(ptr_records > 0, "Answer did not contain any PTR records"); } +int context_destroyed = 0; void destroy_callbackfn(struct getdns_context *context, getdns_callback_type_t callback_type, struct getdns_dict *response, @@ -353,6 +354,7 @@ void destroy_callbackfn(struct getdns_context *context, *flag = 1; getdns_dict_destroy(response); getdns_context_destroy(context); + context_destroyed = 1; } /* diff --git a/src/test/check_getdns_context_destroy.h b/src/test/check_getdns_context_destroy.h index fe3739dc..f4dd97ab 100644 --- a/src/test/check_getdns_context_destroy.h +++ b/src/test/check_getdns_context_destroy.h @@ -28,6 +28,7 @@ #define _check_getdns_context_destroy_h_ #include +extern int context_destroyed; /* ************************************************************************** @@ -202,10 +203,12 @@ &flag, &transaction_id, destroy_callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_address()"); + context_destroyed = 0; RUN_EVENT_LOOP; - CONTEXT_DESTROY; - + if (!context_destroyed) { + CONTEXT_DESTROY; + } ck_assert_msg(flag == 1, "flag should == 1, got %d", flag); } END_TEST @@ -229,10 +232,11 @@ &flag, &transaction_id, destroy_callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_address()"); getdns_cancel_callback(context, transaction_id); + context_destroyed = 0; RUN_EVENT_LOOP; - - CONTEXT_DESTROY; - + if (!context_destroyed) { + CONTEXT_DESTROY; + } ck_assert_msg(flag == 1, "flag should == 1, got %d", flag); } END_TEST @@ -261,10 +265,12 @@ &flag, &transaction_id, destroy_callbackfn), GETDNS_RETURN_GOOD, "Return code from getdns_address()"); + context_destroyed = 0; RUN_EVENT_LOOP; - CONTEXT_DESTROY; - + if (!context_destroyed) { + CONTEXT_DESTROY; + } ck_assert_msg(flag == 1, "flag should == 1, got %d", flag); } END_TEST