]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
ares: destroy channel on shutdown
authorStefan Eissing <stefan@eissing.org>
Thu, 7 Aug 2025 08:32:14 +0000 (10:32 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 7 Aug 2025 09:35:35 +0000 (11:35 +0200)
When we cancel async resolv operations, we have kept an existing ares
channel open. This seems unreliable as reported in #18216.

To get reliable behaviour, always destroy the ares channel on async
shutdown and create a new one on demand.

Fixes #18216
Reported-by: devgs on github
Closes #18217

lib/asyn-ares.c

index 375f1a6eb625ac08766cb1125fd6039fd5bbc8d3..815d7ab57fcdea84bab69c810ee8ed6fe4fba8c3 100644 (file)
@@ -237,26 +237,6 @@ CURLcode Curl_async_get_impl(struct Curl_easy *data, void **impl)
   return result;
 }
 
-static void async_ares_cleanup(struct Curl_easy *data);
-
-void Curl_async_ares_shutdown(struct Curl_easy *data)
-{
-  struct async_ares_ctx *ares = &data->state.async.ares;
-  if(ares->channel)
-    ares_cancel(ares->channel);
-  async_ares_cleanup(data);
-}
-
-void Curl_async_ares_destroy(struct Curl_easy *data)
-{
-  struct async_ares_ctx *ares = &data->state.async.ares;
-  Curl_async_ares_shutdown(data);
-  if(ares->channel) {
-    ares_destroy(ares->channel);
-    ares->channel = NULL;
-  }
-}
-
 /*
  * async_ares_cleanup() cleans up async resolver data.
  */
@@ -272,6 +252,26 @@ static void async_ares_cleanup(struct Curl_easy *data)
 #endif
 }
 
+void Curl_async_ares_shutdown(struct Curl_easy *data)
+{
+  /* c-ares has a method to "cancel" operations on a channel, but
+   * as reported in #18216, this does not totally reset the channel
+   * and ares may get stuck.
+   * We need to destroy the channel and on demand create a new
+   * one to avoid that. */
+  Curl_async_ares_destroy(data);
+}
+
+void Curl_async_ares_destroy(struct Curl_easy *data)
+{
+  struct async_ares_ctx *ares = &data->state.async.ares;
+  if(ares->channel) {
+    ares_destroy(ares->channel);
+    ares->channel = NULL;
+  }
+  async_ares_cleanup(data);
+}
+
 /*
  * Curl_async_pollset() is called when someone from the outside world
  * (using curl_multi_fdset()) wants to get our fd_set setup.