Fix a potentially very annoying evdns bug that we found in Tor.

Generally speaking, it way better to event_assign() an event when you
allocate it than to assign it before every time you event_add it: if
it is already event_add()ed, the assign will mess it up so that it
doesn't _look_ added, and event_add() will insert a second copy.
Later, event_del() will only delete the second copy.  Eventually, the
event_base will have a dangling pointer to freed memory.  Ouch!

svn:r1308
This commit is contained in:
Nick Mathewson 2009-05-22 18:32:09 +00:00
parent 6bd85f9d71
commit 9d0f6eb4e2
2 changed files with 5 additions and 3 deletions

View File

@ -1,5 +1,6 @@
Changes in 1.4.12-stable:
o Try to contain degree of failure when running on a win32 version so heavily firewalled that we can't fake a socketpair.
o Fix an obscure timing-dependent, allocator-dependent crash in the evdns code.
Changes in 1.4.11-stable:
o Fix a bug when removing a timeout from the heap. [Patch from Marko Kreen]

View File

@ -469,7 +469,6 @@ nameserver_probe_failed(struct nameserver *const ns) {
global_nameserver_timeouts_length - 1)];
ns->failed_times++;
evtimer_set(&ns->timeout_event, nameserver_prod_callback, ns);
if (evtimer_add(&ns->timeout_event, (struct timeval *) timeout) < 0) {
log(EVDNS_LOG_WARN,
"Error from libevent when adding timer event for %s",
@ -498,7 +497,6 @@ nameserver_failed(struct nameserver *const ns, const char *msg) {
ns->state = 0;
ns->failed_times = 1;
evtimer_set(&ns->timeout_event, nameserver_prod_callback, ns);
if (evtimer_add(&ns->timeout_event, (struct timeval *) &global_nameserver_timeouts[0]) < 0) {
log(EVDNS_LOG_WARN,
"Error from libevent when adding timer event for %s",
@ -1941,7 +1939,6 @@ evdns_request_transmit(struct request *req) {
/* all ok */
log(EVDNS_LOG_DEBUG,
"Setting timeout for request %lx", (unsigned long) req);
evtimer_set(&req->timeout_event, evdns_request_timeout_callback, req);
if (evtimer_add(&req->timeout_event, &global_timeout) < 0) {
log(EVDNS_LOG_WARN,
"Error from libevent when adding timer for request %lx",
@ -2102,6 +2099,8 @@ _evdns_nameserver_add_impl(unsigned long int address, int port) {
memset(ns, 0, sizeof(struct nameserver));
evtimer_set(&ns->timeout_event, nameserver_prod_callback, ns);
ns->socket = socket(PF_INET, SOCK_DGRAM, 0);
if (ns->socket < 0) { err = 1; goto out1; }
evutil_make_socket_nonblocking(ns->socket);
@ -2226,6 +2225,8 @@ request_new(int type, const char *name, int flags,
if (!req) return NULL;
memset(req, 0, sizeof(struct request));
evtimer_set(&req->timeout_event, evdns_request_timeout_callback, req);
/* request data lives just after the header */
req->request = ((u8 *) req) + sizeof(struct request);
/* denotes that the request data shouldn't be free()ed */