mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-10 04:50:37 -04:00
Make evdns_getaddrinfo_cancel threadsafe
This commit is contained in:
parent
c7cfbcf466
commit
d51b2fc655
34
evdns.c
34
evdns.c
@ -4060,6 +4060,9 @@ struct evdns_getaddrinfo_request {
|
|||||||
int pending_error;
|
int pending_error;
|
||||||
/* If this is set, the user canceled this request. */
|
/* If this is set, the user canceled this request. */
|
||||||
unsigned user_canceled : 1;
|
unsigned user_canceled : 1;
|
||||||
|
/* If this is set, the user can no longer cancel this request; we're
|
||||||
|
* just waiting for the free. */
|
||||||
|
unsigned request_done : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Convert an evdns errors to the equivalent getaddrinfo error. */
|
/* Convert an evdns errors to the equivalent getaddrinfo error. */
|
||||||
@ -4189,29 +4192,32 @@ evdns_getaddrinfo_gotresolve(int result, char type, int count,
|
|||||||
int socklen, addrlen;
|
int socklen, addrlen;
|
||||||
void *addrp;
|
void *addrp;
|
||||||
int err;
|
int err;
|
||||||
|
int user_canceled;
|
||||||
|
|
||||||
EVUTIL_ASSERT(req->type == DNS_IPv4_A || req->type == DNS_IPv6_AAAA);
|
EVUTIL_ASSERT(req->type == DNS_IPv4_A || req->type == DNS_IPv6_AAAA);
|
||||||
if (req->type == DNS_IPv4_A) {
|
if (req->type == DNS_IPv4_A) {
|
||||||
data = EVUTIL_UPCAST(req, struct evdns_getaddrinfo_request, ipv4_request);
|
data = EVUTIL_UPCAST(req, struct evdns_getaddrinfo_request, ipv4_request);
|
||||||
other_req = &data->ipv6_request;
|
other_req = &data->ipv6_request;
|
||||||
if (evdns_result_is_answer(result)) {
|
|
||||||
EVDNS_LOCK(data->evdns_base);
|
|
||||||
++data->evdns_base->getaddrinfo_ipv4_answered;
|
|
||||||
EVDNS_UNLOCK(data->evdns_base);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
data = EVUTIL_UPCAST(req, struct evdns_getaddrinfo_request, ipv6_request);
|
data = EVUTIL_UPCAST(req, struct evdns_getaddrinfo_request, ipv6_request);
|
||||||
other_req = &data->ipv4_request;
|
other_req = &data->ipv4_request;
|
||||||
if (evdns_result_is_answer(result)) {
|
}
|
||||||
|
|
||||||
EVDNS_LOCK(data->evdns_base);
|
EVDNS_LOCK(data->evdns_base);
|
||||||
|
if (evdns_result_is_answer(result)) {
|
||||||
|
if (req->type == DNS_IPv4_A)
|
||||||
|
++data->evdns_base->getaddrinfo_ipv4_answered;
|
||||||
|
else
|
||||||
++data->evdns_base->getaddrinfo_ipv6_answered;
|
++data->evdns_base->getaddrinfo_ipv6_answered;
|
||||||
|
}
|
||||||
|
user_canceled = data->user_canceled;
|
||||||
|
if (other_req->r == NULL)
|
||||||
|
data->request_done = 1;
|
||||||
EVDNS_UNLOCK(data->evdns_base);
|
EVDNS_UNLOCK(data->evdns_base);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
req->r = NULL;
|
req->r = NULL;
|
||||||
|
|
||||||
if (result == DNS_ERR_CANCEL && ! data->user_canceled) {
|
if (result == DNS_ERR_CANCEL && ! user_canceled) {
|
||||||
/* Internal cancel request from timeout or internal error.
|
/* Internal cancel request from timeout or internal error.
|
||||||
* we already answered the user. */
|
* we already answered the user. */
|
||||||
if (other_req->r == NULL)
|
if (other_req->r == NULL)
|
||||||
@ -4239,7 +4245,7 @@ evdns_getaddrinfo_gotresolve(int result, char type, int count,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->user_canceled) {
|
if (user_canceled) {
|
||||||
data->user_cb(EVUTIL_EAI_CANCEL, NULL, data->user_data);
|
data->user_cb(EVUTIL_EAI_CANCEL, NULL, data->user_data);
|
||||||
} else if (data->pending_result) {
|
} else if (data->pending_result) {
|
||||||
/* If we have an answer waiting, and we weren't
|
/* If we have an answer waiting, and we weren't
|
||||||
@ -4255,7 +4261,7 @@ evdns_getaddrinfo_gotresolve(int result, char type, int count,
|
|||||||
}
|
}
|
||||||
free_getaddrinfo_request(data);
|
free_getaddrinfo_request(data);
|
||||||
return;
|
return;
|
||||||
} else if (data->user_canceled) {
|
} else if (user_canceled) {
|
||||||
if (other_req->r) {
|
if (other_req->r) {
|
||||||
/* The other request is still working; let it hit this
|
/* The other request is still working; let it hit this
|
||||||
* callback with EVUTIL_EAI_CANCEL callback and report
|
* callback with EVUTIL_EAI_CANCEL callback and report
|
||||||
@ -4524,10 +4530,16 @@ evdns_getaddrinfo(struct evdns_base *dns_base,
|
|||||||
void
|
void
|
||||||
evdns_getaddrinfo_cancel(struct evdns_getaddrinfo_request *data)
|
evdns_getaddrinfo_cancel(struct evdns_getaddrinfo_request *data)
|
||||||
{
|
{
|
||||||
|
EVDNS_LOCK(data->evdns_base);
|
||||||
|
if (data->request_done) {
|
||||||
|
EVDNS_UNLOCK(data->evdns_base);
|
||||||
|
return;
|
||||||
|
}
|
||||||
event_del(&data->timeout);
|
event_del(&data->timeout);
|
||||||
data->user_canceled = 1;
|
data->user_canceled = 1;
|
||||||
if (data->ipv4_request.r)
|
if (data->ipv4_request.r)
|
||||||
evdns_cancel_request(data->evdns_base, data->ipv4_request.r);
|
evdns_cancel_request(data->evdns_base, data->ipv4_request.r);
|
||||||
if (data->ipv6_request.r)
|
if (data->ipv6_request.r)
|
||||||
evdns_cancel_request(data->evdns_base, data->ipv6_request.r);
|
evdns_cancel_request(data->evdns_base, data->ipv6_request.r);
|
||||||
|
EVDNS_UNLOCK(data->evdns_base);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user