Possible fix for #21 and tests

This commit is contained in:
Neel Goyal 2014-03-05 22:13:37 -05:00
parent 6ab9ce861b
commit 3f8e8ac098
8 changed files with 107 additions and 29 deletions

View File

@ -541,6 +541,9 @@ getdns_context_destroy(struct getdns_context *context)
context->processing++;
return;
}
if (context->destroying) {
return;
}
context->destroying = 1;
cancel_outstanding_requests(context, 1);
getdns_extension_detach_eventloop(context);
@ -1210,11 +1213,18 @@ getdns_cancel_callback(struct getdns_context *context,
getdns_transaction_t transaction_id)
{
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
context->processing = 1;
getdns_return_t r = getdns_context_cancel_request(context, transaction_id, 1);
if (context->extension) {
context->extension->request_count_changed(context,
context->outbound_requests->count, context->extension_data);
}
if (context->processing > 1) {
context->processing = 0;
getdns_context_destroy(context);
return GETDNS_RETURN_BAD_CONTEXT;
}
context->processing = 0;
return r;
} /* getdns_cancel_callback */
@ -1417,7 +1427,32 @@ getdns_context_clear_outbound_request(getdns_dns_req * req)
return GETDNS_RETURN_GOOD;
}
getdns_return_t
getdns_context_request_timed_out(struct getdns_dns_req
*req) {
getdns_context* context = req->context;
getdns_transaction_t trans_id = req->trans_id;
getdns_callback_t cb = req->user_callback;
void *user_arg = req->user_pointer;
/* cancel the req - also clears it from outbound and cleans up*/
getdns_context_cancel_request(context, trans_id, 0);
context->processing = 1;
cb(context, GETDNS_CALLBACK_TIMEOUT, NULL, user_arg, trans_id);
if (context->processing > 1) {
// destroyed.
context->processing = 0;
getdns_context_destroy(context);
return GETDNS_RETURN_BAD_CONTEXT;
} else {
context->processing = 0;
if (context->extension) {
context->extension->request_count_changed(context,
context->outbound_requests->count, context->extension_data);
}
}
return GETDNS_RETURN_GOOD;
}
char *
getdns_strdup(const struct mem_funcs *mfs, const char *s)
@ -1543,7 +1578,8 @@ getdns_return_t getdns_context_process_async(struct getdns_context* context) {
return GETDNS_RETURN_GENERIC_ERROR;
}
ldns_rbnode_t* next_timeout = ldns_rbtree_first(context->timeouts_by_time);
while (next_timeout) {
getdns_return_t r = GETDNS_RETURN_GOOD;
while (next_timeout && r == GETDNS_RETURN_GOOD) {
getdns_timeout_data_t* timeout_data = (getdns_timeout_data_t*) next_timeout->data;
if (timeout_cmp(timeout_data, &key) > 0) {
/* no more timeouts need to be fired. */
@ -1560,10 +1596,10 @@ getdns_return_t getdns_context_process_async(struct getdns_context* context) {
}
/* fire the timeout */
timeout_data->callback(timeout_data->userarg);
r = timeout_data->callback(timeout_data->userarg);
}
return GETDNS_RETURN_GOOD;
return r;
}
typedef struct timeout_accumulator {

View File

@ -157,6 +157,10 @@ getdns_return_t getdns_context_track_outbound_request(struct getdns_dns_req
/* clear the outbound request from being tracked - does not cancel it */
getdns_return_t getdns_context_clear_outbound_request(struct getdns_dns_req
*req);
getdns_return_t getdns_context_request_timed_out(struct getdns_dns_req
*req);
/* cancel callback internal - flag to indicate if req should be freed and callback fired */
getdns_return_t getdns_context_cancel_request(struct getdns_context *context,
getdns_transaction_t transaction_id, int fire_callback);

View File

@ -73,10 +73,6 @@ static void
getdns_libev_timeout_cb(struct ev_loop *loop, struct ev_timer* handle, int status) {
getdns_timeout_data_t* timeout_data = (getdns_timeout_data_t*) handle->data;
timeout_data->callback(timeout_data->userarg);
uint32_t rc = getdns_context_get_num_pending_requests(timeout_data->context, NULL);
struct getdns_libev_data* ev_data =
(struct getdns_libev_data*) getdns_context_get_extension_data(timeout_data->context);
request_count_changed(rc, ev_data);
}
/* getdns extension functions */

View File

@ -102,10 +102,6 @@ static void
getdns_libevent_timeout_cb(evutil_socket_t fd, short what, void* userarg) {
getdns_timeout_data_t* timeout_data = (getdns_timeout_data_t*) userarg;
timeout_data->callback(timeout_data->userarg);
uint32_t rc = getdns_context_get_num_pending_requests(timeout_data->context, NULL);
struct event_data* ev_data =
(struct event_data*) getdns_context_get_extension_data(timeout_data->context);
request_count_changed(rc, ev_data);
}
/* getdns extension functions */

View File

@ -75,10 +75,6 @@ static void
getdns_libuv_timeout_cb(uv_timer_t* handle, int status) {
getdns_timeout_data_t* timeout_data = (getdns_timeout_data_t*) handle->data;
timeout_data->callback(timeout_data->userarg);
uint32_t rc = getdns_context_get_num_pending_requests(timeout_data->context, NULL);
struct getdns_libuv_data* uv_data =
(struct getdns_libuv_data*) getdns_context_get_extension_data(timeout_data->context);
request_count_changed(rc, uv_data);
}
static void

View File

@ -50,8 +50,8 @@
/* declarations */
static void ub_resolve_callback(void* mydata, int err, struct ub_result* result);
static void ub_resolve_timeout(void *arg);
static void ub_local_resolve_timeout(void *arg);
static getdns_return_t ub_resolve_timeout(void *arg);
static getdns_return_t ub_local_resolve_timeout(void *arg);
static void handle_network_request_error(getdns_network_req * netreq, int err);
static void handle_dns_request_complete(getdns_dns_req * dns_req);
@ -65,22 +65,14 @@ typedef struct netreq_cb_data
} netreq_cb_data;
/* cancel, cleanup and send timeout to callback */
static void
static getdns_return_t
ub_resolve_timeout(void *arg)
{
getdns_dns_req *dns_req = (getdns_dns_req *) arg;
struct getdns_context *context = dns_req->context;
getdns_transaction_t trans_id = dns_req->trans_id;
getdns_callback_t cb = dns_req->user_callback;
void *user_arg = dns_req->user_pointer;
/* cancel the req - also clears it from outbound and cleans up*/
getdns_context_cancel_request(context, trans_id, 0);
cb(context, GETDNS_CALLBACK_TIMEOUT, NULL, user_arg, trans_id);
return getdns_context_request_timed_out(dns_req);
}
static void
static getdns_return_t
ub_local_resolve_timeout(void *arg)
{
netreq_cb_data *cb_data = (netreq_cb_data *) arg;
@ -99,6 +91,7 @@ ub_local_resolve_timeout(void *arg)
/* cleanup the state */
GETDNS_FREE(dnsreq->my_mf, cb_data);
return GETDNS_RETURN_GOOD;
}
void priv_getdns_call_user_callback(getdns_dns_req *dns_req,

View File

@ -63,7 +63,7 @@ getdns_return_t getdns_context_process_async(getdns_context* context);
getdns_return_t getdns_context_set_use_threads(getdns_context* context, int use_threads);
/* extensions */
typedef void (*getdns_timeout_callback) (void* userarg);
typedef getdns_return_t (*getdns_timeout_callback) (void* userarg);
/* context timeout data */
typedef struct getdns_timeout_data {

View File

@ -202,6 +202,61 @@
}
END_TEST
START_TEST (getdns_context_destroy_8)
{
/*
* destroy called immediately following getdns_address
* expect: callback should be called before getdns_context_destroy() returns
*/
struct getdns_context *context = NULL;
void* eventloop = NULL;
getdns_transaction_t transaction_id = 0;
int flag = 0; /* Initialize flag */
CONTEXT_CREATE(TRUE);
EVENT_BASE_CREATE;
ASSERT_RC(getdns_address(context, "google.com", NULL,
&flag, &transaction_id, destroy_callbackfn),
GETDNS_RETURN_GOOD, "Return code from getdns_address()");
getdns_cancel_callback(context, transaction_id);
RUN_EVENT_LOOP;
ck_assert_msg(flag == 1, "flag should == 1, got %d", flag);
}
END_TEST
START_TEST (getdns_context_destroy_9)
{
/*
* destroy called immediately following getdns_address
* expect: callback should be called before getdns_context_destroy() returns
*/
struct getdns_context *context = NULL;
void* eventloop = NULL;
getdns_transaction_t transaction_id = 0;
int flag = 0; /* Initialize flag */
CONTEXT_CREATE(TRUE);
// set timeout to something unreasonable
getdns_context_set_timeout(context, 1);
EVENT_BASE_CREATE;
ASSERT_RC(getdns_address(context, "google.com", NULL,
&flag, &transaction_id, destroy_callbackfn),
GETDNS_RETURN_GOOD, "Return code from getdns_address()");
ASSERT_RC(getdns_address(context, "getdnsapi.net", NULL,
&flag, &transaction_id, destroy_callbackfn),
GETDNS_RETURN_GOOD, "Return code from getdns_address()");
RUN_EVENT_LOOP;
ck_assert_msg(flag == 1, "flag should == 1, got %d", flag);
}
END_TEST
void verify_getdns_context_destroy(struct extracted_response *ex_response)
{
/*
@ -234,6 +289,8 @@
tcase_add_test(tc_pos, getdns_context_destroy_5);
tcase_add_test(tc_pos, getdns_context_destroy_6);
tcase_add_test(tc_pos, getdns_context_destroy_7);
tcase_add_test(tc_pos, getdns_context_destroy_8);
tcase_add_test(tc_pos, getdns_context_destroy_9);
suite_add_tcase(s, tc_pos);
return s;