* 'struct request' instances being created over its lifetime. */
struct evdns_request {
struct request *current_req;
+ struct evdns_base *base;
+
+ int pending_cb; /* Waiting for its callback to be invoked; not
+ * owned by event base any more. */
/* elements used by the searching code */
int search_index;
if (req->handle) {
EVUTIL_ASSERT(req->handle->current_req == req);
+
if (free_handle) {
search_request_finished(req->handle);
- mm_free(req->handle);
- } else
req->handle->current_req = NULL;
+ if (! req->handle->pending_cb) {
+ /* If we're planning to run the callback,
+ * don't free the handle until later. */
+ mm_free(req->handle);
+ }
+ req->handle = NULL; /* If we have a bug, let's crash
+ * early */
+ } else {
+ req->handle->current_req = NULL;
+ }
}
mm_free(req);
/* TODO(nickm) document */
struct deferred_reply_callback {
struct deferred_cb deferred;
+ struct evdns_request *handle;
u8 request_type;
u8 have_reply;
u32 ttl;
EVUTIL_ASSERT(0);
}
+ if (cb->handle && cb->handle->pending_cb) {
+ mm_free(cb->handle);
+ }
+
mm_free(cb);
}
memcpy(&d->reply, reply, sizeof(struct reply));
}
+ if (req->handle) {
+ req->handle->pending_cb = 1;
+ d->handle = req->handle;
+ }
+
event_deferred_cb_init(&d->deferred, reply_run_callback,
req->user_pointer);
event_deferred_cb_schedule(
req->ns = issuing_now ? nameserver_pick(base) : NULL;
req->next = req->prev = NULL;
req->handle = handle;
- if (handle)
+ if (handle) {
handle->current_req = req;
+ handle->base = base;
+ }
return req;
err1:
void
evdns_cancel_request(struct evdns_base *base, struct evdns_request *handle)
{
- struct request *req = handle->current_req;
-
- ASSERT_VALID_REQUEST(req);
+ struct request *req;
- if (!base)
- base = req->base;
+ if (!base) {
+ /* This redundancy is silly; can we fix it? (Not for 2.0) XXXX */
+ base = handle->base;
+ if (!base && handle->current_req)
+ base = handle->current_req->base;
+ }
EVDNS_LOCK(base);
+ if (handle->pending_cb) {
+ EVDNS_UNLOCK(base);
+ return;
+ }
+
+ req = handle->current_req;
+ ASSERT_VALID_REQUEST(req);
+
reply_schedule_callback(req, 0, DNS_ERR_CANCEL, NULL);
if (req->ns) {
/* remove from inflight queue */