]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolved: explicitly disconnect all left-over TCP connections when coming back from...
authorLennart Poettering <lennart@poettering.net>
Fri, 1 Mar 2024 20:46:46 +0000 (21:46 +0100)
committerLuca Boccassi <luca.boccassi@gmail.com>
Sat, 2 Mar 2024 18:05:01 +0000 (18:05 +0000)
Fixes: #13730 (original reporter's log shows the TCP connection needed
to time out first)

src/resolve/resolved-bus.c
src/resolve/resolved-dns-stream.c
src/resolve/resolved-dns-stream.h

index d9d967ec400c7fa589362d759835c53c281dbdf5..f83c6545582038fd6b42aa91cddfdc63c07eb0d2 100644 (file)
@@ -13,6 +13,7 @@
 #include "missing_capability.h"
 #include "resolved-bus.h"
 #include "resolved-def.h"
+#include "resolved-dns-stream.h"
 #include "resolved-dns-synthesize.h"
 #include "resolved-dnssd-bus.h"
 #include "resolved-dnssd.h"
@@ -1843,6 +1844,7 @@ static int bus_method_reset_server_features(sd_bus_message *message, void *userd
 
         bus_client_log(message, "server feature reset");
 
+        (void) dns_stream_disconnect_all(m);
         manager_reset_server_features(m);
 
         return sd_bus_reply_method_return(message, NULL);
@@ -2231,9 +2233,15 @@ static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_b
         if (b)
                 return 0;
 
-        log_debug("Coming back from suspend, verifying all RRs...");
+        log_debug("Coming back from suspend, closing all TCP connections...");
+        (void) dns_stream_disconnect_all(m);
+
+        log_debug("Coming back from suspend, resetting all probed server features...");
+        manager_reset_server_features(m);
 
+        log_debug("Coming back from suspend, verifying all RRs...");
         manager_verify_all(m);
+
         return 0;
 }
 
index ddd1db5e09a9785a509abbad0a13fe003eafe33f..056ba7794f5dd2f270b71a6f5c660a5a8c96600b 100644 (file)
@@ -593,3 +593,44 @@ void dns_stream_detach(DnsStream *s) {
 
         dns_server_unref_stream(s->server);
 }
+
+DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
+                dns_stream_hash_ops,
+                void,
+                trivial_hash_func,
+                trivial_compare_func,
+                dns_stream_unref);
+
+int dns_stream_disconnect_all(Manager *m) {
+        _cleanup_(set_freep) Set *closed = NULL;
+        int r;
+
+        assert(m);
+
+        /* Terminates all TCP connections (called after system suspend for example, to speed up recovery) */
+
+        log_info("Closing all remaining TCP connections.");
+
+        bool restart;
+        do {
+                restart = false;
+
+                LIST_FOREACH(streams, s, m->dns_streams) {
+                        r = set_ensure_put(&closed, &dns_stream_hash_ops, s);
+                        if (r < 0)
+                                return log_oom();
+                        if (r > 0) {
+                                /* Haven't seen this one before. Close it. */
+                                dns_stream_ref(s);
+                                (void) dns_stream_complete(s, ECONNRESET);
+
+                                /* This might have a ripple effect, let's hence no look at the list further,
+                                 * but scan from the beginning again */
+                                restart = true;
+                                break;
+                        }
+                }
+        } while (restart);
+
+        return 0;
+}
index ba4a59e41c51bd26216be4d55535c8107f9339c1..912b9bf431205b3486bb789a8d33de3a4bd29e56 100644 (file)
@@ -126,3 +126,4 @@ static inline bool DNS_STREAM_QUEUED(DnsStream *s) {
 }
 
 void dns_stream_detach(DnsStream *s);
+int dns_stream_disconnect_all(Manager *m);