]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Fix] Unschedule DNS request when clearing IO channel
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Sat, 22 Jan 2022 12:29:51 +0000 (12:29 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Sat, 22 Jan 2022 12:29:51 +0000 (12:29 +0000)
contrib/librdns/resolver.c
contrib/librdns/util.c
contrib/librdns/util.h

index 9f5ca9872f910d76613c749c85c3aa8d5b162064..c12180ec1a9673259438d7ecc96e8633a41aa133 100644 (file)
@@ -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) {
index 25a7ab72f6767fd6fe85d9125743eaa3c5692d79..f4c442563052e70fd7cc941a19c6335ad1618b12 100644 (file)
@@ -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);
 }
 
index 915b8febdc968f67d41eb76f41641c710d77db6f..6f74d8b85cd411dbbfe9d1091ea15d3b2da48186 100644 (file)
@@ -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_ */