Author: Stefan Gränitz
Date: 2026-07-13T15:55:13+02:00
New Revision: 290601ed3e08a7e90b81b0b17cf45e1a435783a7

URL: 
https://github.com/llvm/llvm-project/commit/290601ed3e08a7e90b81b0b17cf45e1a435783a7
DIFF: 
https://github.com/llvm/llvm-project/commit/290601ed3e08a7e90b81b0b17cf45e1a435783a7.diff

LOG: [lldb] Make timeout for HTTP send/receive in SymbolLocatorSymStore 
configurable (#192061)

This patch adds the `plugin.symbol-locator.symstore.timeout` setting and
keeps the previously hard-coded value of 60 sections as the default. It
adds a test to check that the breakpoint doesn't resolve and we get the
correct warning message if the timeout hits.

---------

Co-authored-by: Nerixyz <[email protected]>

Added: 
    

Modified: 
    lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
    
lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStoreProperties.td
    lldb/test/API/symstore/TestSymStore.py

Removed: 
    


################################################################################
diff  --git 
a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp 
b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
index fac00c1a12db2..eab334e0b8e7a 100644
--- a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
+++ b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
@@ -68,6 +68,12 @@ class PluginProperties : public Properties {
     return SymbolLocatorSymStore::GetSystemDefaultCachePath();
   }
 
+  uint64_t GetTimeout() const {
+    const uint32_t idx = ePropertyTimeout;
+    return GetPropertyAtIndexAs<uint64_t>(
+        idx, g_symbollocatorsymstore_properties[idx].default_uint_value);
+  }
+
   std::optional<std::string> GetTLSCertFingerprint() const {
     OptionValueString *s =
         m_collection_sp->GetPropertyAtIndexAsOptionValueString(
@@ -272,9 +278,8 @@ RequestFileFromSymStoreServerHTTP(llvm::StringRef base_url, 
llvm::StringRef key,
   }
 
   llvm::HTTPClient client;
-  // TODO: Since PDBs can be huge, we should distinguish between resolve,
-  // connect, send and receive.
-  client.setTimeout(std::chrono::seconds(60));
+  client.setTimeout(
+      std::chrono::seconds(GetGlobalPluginProperties().GetTimeout()));
 
   llvm::StreamedHTTPResponseHandler Handler(
       [dest = tmp_file.str().str()]()

diff  --git 
a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStoreProperties.td 
b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStoreProperties.td
index da24201c66b18..9ffd0cfab4fc0 100644
--- 
a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStoreProperties.td
+++ 
b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStoreProperties.td
@@ -2,12 +2,14 @@ include "../../../../include/lldb/Core/PropertiesBase.td"
 
 let Definition = "symbollocatorsymstore", Path = 
"plugin.symbol-locator.symstore" in {
   def SymStoreURLs : Property<"urls", "Array">,
-                     ElementType<"String">,
-                     Desc<"List of local symstore directories to query after "
-                          "_NT_SYMBOL_PATH">;
+    ElementType<"String">,
+    Desc<"List of local symstore directories to query after _NT_SYMBOL_PATH">;
   def CachePath : Property<"cache", "String">,
     DefaultStringValue<"">,
     Desc<"Default cache directory for downloaded symbol files. Used when no 
cache is specified in _NT_SYMBOL_PATH.">;
+  def Timeout : Property<"timeout", "UInt64">,
+    DefaultUnsignedValue<60>,
+    Desc<"Timeout in seconds for send/receive in HTTP connections to symbol 
servers. A value of 0 indicates an infinite (no) timeout.">;
   def TLSCertFingerprint : Property<"tls-cert-fingerprint", "String">,
     DefaultStringValue<"">,
     Desc<"SHA-256 fingerprint (lowercase hex, no separators) of the symbol 
server's TLS certificate. When set, LLDB will accept an HTTPS server that 
presents this self-signed certificate even if it is not trusted by the system 
certificate store (Windows only).">;

diff  --git a/lldb/test/API/symstore/TestSymStore.py 
b/lldb/test/API/symstore/TestSymStore.py
index 83a3b71b0adfb..4c668134447d1 100644
--- a/lldb/test/API/symstore/TestSymStore.py
+++ b/lldb/test/API/symstore/TestSymStore.py
@@ -7,6 +7,7 @@
 import ssl
 import sys
 import threading
+import time
 from functools import partial
 
 import lldb
@@ -233,6 +234,23 @@ def do_GET(self):
         super().do_GET()
 
 
+class SlowHTTPHandler(http.server.BaseHTTPRequestHandler):
+    """HTTP request handler that delays responses to simulate a slow server."""
+
+    delay = 2  # seconds to sleep before responding; set per test
+
+    def do_GET(self):
+        try:
+            time.sleep(self.delay)
+            self.send_response(200)
+            self.end_headers()
+        except (BrokenPipeError, ConnectionResetError):
+            pass  # client disconnected after timeout, as expected
+
+    def log_message(self, *args):
+        pass  # suppress server-side output
+
+
 class SymStoreTests(TestBase):
     TEST_WITH_PDB_DEBUG_INFO = True
 
@@ -426,6 +444,26 @@ def test_lookup_order(self):
                     self.try_breakpoint(exe, should_have_loc=True)
             self.assertEqual(RequestCounter.requests, 0)
 
+    def test_http_timeout(self):
+        """
+        Check that a warning is emitted and no symbol is found when the server
+        takes longer to respond than the configured timeout.
+        """
+        exe, sym = self.build_inferior()
+        with MockedSymStore(self, exe, sym) as dir:
+            SlowHTTPHandler.delay = 5  # seconds; exceeds the 1s timeout below
+            self.runCmd("settings set plugin.symbol-locator.symstore.timeout 
1")
+            with HTTPServer(dir, SlowHTTPHandler) as url:
+                self.runCmd(f"settings set plugin.symbol-locator.symstore.urls 
{url}")
+                warnings = ""
+                with open(self.getBuildArtifact("stderr.txt"), "w+b") as 
err_file:
+                    self.dbg.SetErrorFileHandle(err_file, False)
+                    self.try_breakpoint(exe, should_have_loc=False)
+                    self.dbg.SetErrorFileHandle(sys.stderr, False)
+                    err_file.seek(0)
+                    warnings = err_file.read().decode()
+                self.assertIn("failed to download", warnings)
+
     @skipUnlessPackageAvailable("cryptography")
     def test_https(self):
         """


        
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to