diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2022-01-22 12:29:51 +0000 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2022-01-22 12:29:51 +0000 |
commit | 982901084d95e6a9a1b955d91ef7cf20ea72c673 (patch) | |
tree | a925a96eb36f4888a27f73a6621af5417222a386 /contrib/librdns | |
parent | 8fb3dc2ad50d23b2bec5dcf1ddeb17c50b8b3b67 (diff) | |
download | rspamd-982901084d95e6a9a1b955d91ef7cf20ea72c673.tar.gz rspamd-982901084d95e6a9a1b955d91ef7cf20ea72c673.zip |
[Fix] Unschedule DNS request when clearing IO channel
Diffstat (limited to 'contrib/librdns')
-rw-r--r-- | contrib/librdns/resolver.c | 8 | ||||
-rw-r--r-- | contrib/librdns/util.c | 42 | ||||
-rw-r--r-- | contrib/librdns/util.h | 2 |
3 files changed, 33 insertions, 19 deletions
diff --git a/contrib/librdns/resolver.c b/contrib/librdns/resolver.c index 9f5ca9872..c12180ec1 100644 --- a/contrib/librdns/resolver.c +++ b/contrib/librdns/resolver.c @@ -549,7 +549,7 @@ rdns_process_udp_read (int fd, struct rdns_io_channel *ioc) req->resolver->ups->data); } - rdns_request_unschedule (req); + rdns_request_unschedule (req, true); if (!(rep->flags & RDNS_TRUNCATED)) { req->state = RDNS_REQUEST_REPLIED; @@ -621,7 +621,7 @@ rdns_process_timer (void *arg) if (req->state == RDNS_REQUEST_TCP) { rep = rdns_make_reply (req, RDNS_RC_TIMEOUT); - rdns_request_unschedule (req); + rdns_request_unschedule (req, true); req->state = RDNS_REQUEST_REPLIED; req->func (rep, req->arg); REF_RELEASE (req); @@ -632,7 +632,7 @@ rdns_process_timer (void *arg) if (req->retransmits == 0) { rep = rdns_make_reply (req, RDNS_RC_TIMEOUT); - rdns_request_unschedule (req); + rdns_request_unschedule (req, true); req->state = RDNS_REQUEST_REPLIED; req->func (rep, req->arg); REF_RELEASE (req); @@ -655,7 +655,7 @@ rdns_process_timer (void *arg) if (!IS_CHANNEL_ACTIVE(req->io) || cnt > 1) { /* Do not reschedule IO requests on inactive sockets */ rdns_debug ("reschedule request with id: %d", (int)req->id); - rdns_request_unschedule (req); + rdns_request_unschedule (req, true); REF_RELEASE (req->io); if (resolver->ups) { diff --git a/contrib/librdns/util.c b/contrib/librdns/util.c index 25a7ab72f..f4c442563 100644 --- a/contrib/librdns/util.c +++ b/contrib/librdns/util.c @@ -633,25 +633,31 @@ rdns_request_retain (struct rdns_request *req) } void -rdns_request_unschedule (struct rdns_request *req) +rdns_request_unschedule (struct rdns_request *req, bool remove_from_hash) { if (req->async_event) { if (req->state == RDNS_REQUEST_WAIT_REPLY) { req->async->del_timer (req->async->data, req->async_event); - rdns_request_remove_from_hash(req); + if (remove_from_hash) { + rdns_request_remove_from_hash(req); + } req->async_event = NULL; } else if (req->state == RDNS_REQUEST_WAIT_SEND) { req->async->del_write (req->async->data, req->async_event); /* Remove from id hashes */ - rdns_request_remove_from_hash(req); + if (remove_from_hash) { + rdns_request_remove_from_hash(req); + } req->async_event = NULL; } } else if (req->state == RDNS_REQUEST_TCP) { - rdns_request_remove_from_hash(req); + if (remove_from_hash) { + rdns_request_remove_from_hash(req); + } req->async->del_timer(req->async->data, req->async_event); @@ -663,7 +669,7 @@ rdns_request_unschedule (struct rdns_request *req) void rdns_request_release (struct rdns_request *req) { - rdns_request_unschedule (req); + rdns_request_unschedule (req, true); REF_RELEASE (req); } @@ -701,24 +707,32 @@ rdns_ioc_tcp_reset (struct rdns_io_channel *ioc) ioc->flags &= ~RDNS_CHANNEL_CONNECTED; } - if (ioc->sock != -1) { - close (ioc->sock); - ioc->sock = -1; - } - if (ioc->saddr) { - free (ioc->saddr); - ioc->saddr = NULL; - } - /* Remove all requests pending as we are unable to complete them */ struct rdns_request *req; kh_foreach_value(ioc->requests, req, { struct rdns_reply *rep = rdns_make_reply (req, RDNS_RC_NETERR); + /* + * Unschedule request explicitly as we set state to RDNS_REQUEST_REPLIED + * that will prevent timer from being removed on req dtor. + * + * We skip hash removal here, as the hash will be cleared as a single + * operation afterwards. + */ + rdns_request_unschedule(req, false); req->state = RDNS_REQUEST_REPLIED; req->func (rep, req->arg); REF_RELEASE (req); }); + if (ioc->sock != -1) { + close (ioc->sock); + ioc->sock = -1; + } + if (ioc->saddr) { + free (ioc->saddr); + ioc->saddr = NULL; + } + kh_clear(rdns_requests_hash, ioc->requests); } diff --git a/contrib/librdns/util.h b/contrib/librdns/util.h index 915b8febd..6f74d8b85 100644 --- a/contrib/librdns/util.h +++ b/contrib/librdns/util.h @@ -94,6 +94,6 @@ struct rdns_reply * rdns_make_reply (struct rdns_request *req, enum dns_rcode rc */ void rdns_reply_free (struct rdns_reply *rep); -void rdns_request_unschedule (struct rdns_request *req); +void rdns_request_unschedule (struct rdns_request *req, bool remove_from_hash); #endif /* UTIL_H_ */ |