[Lldb-commits] [lldb] [llvm] [lldb-dap] Add unknown request handler (PR #181109)

Sergei Druzhkov via lldb-commits lldb-commits at lists.llvm.org
Fri Feb 13 00:18:03 PST 2026


https://github.com/DrSergei updated https://github.com/llvm/llvm-project/pull/181109

>From eee4f783fce56b5328b39170a4da0b6455347813 Mon Sep 17 00:00:00 2001
From: Sergei Druzhkov <serzhdruzhok at gmail.com>
Date: Thu, 12 Feb 2026 12:24:58 +0300
Subject: [PATCH 1/5] [lldb-dap] Add unknown request handler

---
 .../test/tools/lldb-dap/dap_server.py         |  8 ++++++
 .../launch/TestDAP_launch_unknown_request.py  | 25 +++++++++++++++++++
 lldb/tools/lldb-dap/CMakeLists.txt            |  1 +
 lldb/tools/lldb-dap/DAP.cpp                   | 14 +++++------
 lldb/tools/lldb-dap/DAP.h                     |  2 ++
 lldb/tools/lldb-dap/Handler/RequestHandler.h  |  9 +++++++
 .../Handler/UnknownRequestHandler.cpp         | 19 ++++++++++++++
 .../lldb-dap/Protocol/ProtocolRequests.h      |  5 ++++
 .../gn/secondary/lldb/tools/lldb-dap/BUILD.gn |  1 +
 9 files changed, 76 insertions(+), 8 deletions(-)
 create mode 100644 lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_unknown_request.py
 create mode 100644 lldb/tools/lldb-dap/Handler/UnknownRequestHandler.cpp

diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
index fdccc9eae9fe4..7bbad52147747 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
@@ -1677,6 +1677,14 @@ def request_testGetTargetBreakpoints(self):
         }
         return self._send_recv(command_dict)
 
+    def request_unknown(self):
+        command_dict = {
+            "command": "unknown",
+            "type": "request",
+            "arguments": {},
+        }
+        return self._send_recv(command_dict)
+
     def terminate(self):
         self.send.close()
         if self._recv_thread.is_alive():
diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_unknown_request.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_unknown_request.py
new file mode 100644
index 0000000000000..ac285bce07258
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_unknown_request.py
@@ -0,0 +1,25 @@
+"""
+Test lldb-dap launch request.
+"""
+
+from lldbsuite.test.decorators import expectedFailureWindows
+import lldbdap_testcase
+
+
+class TestDAP_launch_unknown_request(lldbdap_testcase.DAPTestCaseBase):
+    """
+    Tests handling of unknown request.
+    """
+
+    @expectedFailureWindows(
+        bugnumber="https://github.com/llvm/llvm-project/issues/137599"
+    )
+    def test(self):
+        program = self.getBuildArtifact("a.out")
+        self.build_and_launch(program)
+
+        response = self.dap_server.request_unknown()
+        self.assertFalse(response["success"])
+        self.assertEqual(response["body"]["error"]["format"], "Unknown request")
+
+        self.continue_to_exit()
diff --git a/lldb/tools/lldb-dap/CMakeLists.txt b/lldb/tools/lldb-dap/CMakeLists.txt
index 8566c663fcc06..1bb7a2e498b9b 100644
--- a/lldb/tools/lldb-dap/CMakeLists.txt
+++ b/lldb/tools/lldb-dap/CMakeLists.txt
@@ -64,6 +64,7 @@ add_lldb_library(lldbDAP
   Handler/StepOutRequestHandler.cpp
   Handler/TestGetTargetBreakpointsRequestHandler.cpp
   Handler/ThreadsRequestHandler.cpp
+  Handler/UnknownRequestHandler.cpp
   Handler/VariablesRequestHandler.cpp
   Handler/WriteMemoryRequestHandler.cpp
 
diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp
index b76b05c5d1459..0a0d3c3903409 100644
--- a/lldb/tools/lldb-dap/DAP.cpp
+++ b/lldb/tools/lldb-dap/DAP.cpp
@@ -849,15 +849,11 @@ bool DAP::HandleObject(const Message &M) {
     auto handler_pos = request_handlers.find(req->command);
     dispatcher.Set("client_data",
                    llvm::Twine("request_command:", req->command).str());
-    if (handler_pos != request_handlers.end()) {
+    if (handler_pos != request_handlers.end())
       handler_pos->second->Run(*req);
-      return true; // Success
-    }
-
-    dispatcher.Set("error",
-                   llvm::Twine("unhandled-command:" + req->command).str());
-    DAP_LOG(log, "error: unhandled command '{0}'", req->command);
-    return false; // Fail
+    else
+      unknown_request_handler->Run(*req);
+    return true; // Success
   }
 
   if (const auto *resp = std::get_if<Response>(&M)) {
@@ -1577,6 +1573,8 @@ void DAP::RegisterRequests() {
   RegisterRequest<VariablesRequestHandler>();
   RegisterRequest<WriteMemoryRequestHandler>();
 
+  unknown_request_handler = std::make_unique<UnknownRequestHandler>(*this);
+
   // Custom requests
   RegisterRequest<CompileUnitsRequestHandler>();
   RegisterRequest<ModulesRequestHandler>();
diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h
index 34d6a29b3c110..f2e1162eb3a61 100644
--- a/lldb/tools/lldb-dap/DAP.h
+++ b/lldb/tools/lldb-dap/DAP.h
@@ -482,6 +482,8 @@ struct DAP final : public DAPTransport::MessageHandler {
   llvm::StringMap<std::unique_ptr<BaseRequestHandler>> request_handlers;
   /// @}
 
+  std::unique_ptr<BaseRequestHandler> unknown_request_handler;
+
   /// Event threads.
   /// @{
   void ProgressEventThread();
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h b/lldb/tools/lldb-dap/Handler/RequestHandler.h
index 9feb636fd5c28..4b4f1435e7acb 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.h
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h
@@ -658,6 +658,15 @@ class WriteMemoryRequestHandler final
   Run(const protocol::WriteMemoryArguments &args) const override;
 };
 
+class UnknownRequestHandler final
+    : public RequestHandler<protocol::UnknownArguments,
+                            protocol::UnknownResponseBody> {
+public:
+  using RequestHandler::RequestHandler;
+  static llvm::StringLiteral GetCommand() { return "unknown"; }
+  llvm::Error Run(const protocol::UnknownArguments &args) const override;
+};
+
 } // namespace lldb_dap
 
 #endif
diff --git a/lldb/tools/lldb-dap/Handler/UnknownRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/UnknownRequestHandler.cpp
new file mode 100644
index 0000000000000..c576256a48265
--- /dev/null
+++ b/lldb/tools/lldb-dap/Handler/UnknownRequestHandler.cpp
@@ -0,0 +1,19 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "DAPError.h"
+#include "Protocol/ProtocolRequests.h"
+#include "RequestHandler.h"
+#include "llvm/Support/Error.h"
+
+using namespace lldb_dap;
+using namespace lldb_dap::protocol;
+
+llvm::Error UnknownRequestHandler::Run(const UnknownArguments &args) const {
+  return llvm::make_error<DAPError>("Unknown request");
+}
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
index 28c9f48200e0c..91fc2a4db6f57 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
@@ -1312,6 +1312,11 @@ struct StackTraceResponseBody {
 };
 llvm::json::Value toJSON(const StackTraceResponseBody &);
 
+/// Arguments for unknown request.
+using UnknownArguments = EmptyArguments;
+/// Response to unknowns request.
+using UnknownResponseBody = VoidResponse;
+
 } // namespace lldb_dap::protocol
 
 #endif
diff --git a/llvm/utils/gn/secondary/lldb/tools/lldb-dap/BUILD.gn b/llvm/utils/gn/secondary/lldb/tools/lldb-dap/BUILD.gn
index 896da7df95bb1..edcbc5e31f4f1 100644
--- a/llvm/utils/gn/secondary/lldb/tools/lldb-dap/BUILD.gn
+++ b/llvm/utils/gn/secondary/lldb/tools/lldb-dap/BUILD.gn
@@ -68,6 +68,7 @@ static_library("lib") {
     "Handler/StepOutRequestHandler.cpp",
     "Handler/TestGetTargetBreakpointsRequestHandler.cpp",
     "Handler/ThreadsRequestHandler.cpp",
+    "Handler/UnknownRequestHandler.cpp",
     "Handler/VariablesRequestHandler.cpp",
     "Handler/WriteMemoryRequestHandler.cpp",
     "InstructionBreakpoint.cpp",

>From 579d52f78613d1c33b8b7919440c89b90895ea90 Mon Sep 17 00:00:00 2001
From: Sergei Druzhkov <serzhdruzhok at gmail.com>
Date: Thu, 12 Feb 2026 15:52:52 +0300
Subject: [PATCH 2/5] Fix review comments

---
 .../lldbsuite/test/tools/lldb-dap/dap_server.py   |  6 +++---
 lldb/test/API/tools/lldb-dap/custom/Makefile      |  3 +++
 .../TestDAP_unknownRequest.py}                    | 15 +++++++--------
 lldb/test/API/tools/lldb-dap/custom/main.c        |  6 ++++++
 lldb/tools/lldb-dap/DAP.cpp                       | 10 +++++-----
 lldb/tools/lldb-dap/DAP.h                         |  2 --
 6 files changed, 24 insertions(+), 18 deletions(-)
 create mode 100644 lldb/test/API/tools/lldb-dap/custom/Makefile
 rename lldb/test/API/tools/lldb-dap/{launch/TestDAP_launch_unknown_request.py => custom/TestDAP_unknownRequest.py} (50%)
 create mode 100644 lldb/test/API/tools/lldb-dap/custom/main.c

diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
index 7bbad52147747..751832668c5d1 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
@@ -1677,11 +1677,11 @@ def request_testGetTargetBreakpoints(self):
         }
         return self._send_recv(command_dict)
 
-    def request_unknown(self):
+    def request_custom(self, command: str, arguments: Optional[dict[str, Any]] = None):
         command_dict = {
-            "command": "unknown",
+            "command": command,
             "type": "request",
-            "arguments": {},
+            "arguments": {} if arguments is None else arguments,
         }
         return self._send_recv(command_dict)
 
diff --git a/lldb/test/API/tools/lldb-dap/custom/Makefile b/lldb/test/API/tools/lldb-dap/custom/Makefile
new file mode 100644
index 0000000000000..10495940055b6
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/custom/Makefile
@@ -0,0 +1,3 @@
+C_SOURCES := main.c
+
+include Makefile.rules
diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_unknown_request.py b/lldb/test/API/tools/lldb-dap/custom/TestDAP_unknownRequest.py
similarity index 50%
rename from lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_unknown_request.py
rename to lldb/test/API/tools/lldb-dap/custom/TestDAP_unknownRequest.py
index ac285bce07258..ff38f0188a986 100644
--- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_unknown_request.py
+++ b/lldb/test/API/tools/lldb-dap/custom/TestDAP_unknownRequest.py
@@ -1,25 +1,24 @@
 """
-Test lldb-dap launch request.
+Test lldb-dap custom request.
 """
 
 from lldbsuite.test.decorators import expectedFailureWindows
 import lldbdap_testcase
 
 
-class TestDAP_launch_unknown_request(lldbdap_testcase.DAPTestCaseBase):
+class TestDAP_unknown_request(lldbdap_testcase.DAPTestCaseBase):
     """
     Tests handling of unknown request.
     """
 
-    @expectedFailureWindows(
-        bugnumber="https://github.com/llvm/llvm-project/issues/137599"
-    )
     def test(self):
         program = self.getBuildArtifact("a.out")
-        self.build_and_launch(program)
+        self.build_and_launch(program, stopOnEntry=True)
+        self.dap_server.request_configurationDone()
+        self.dap_server.wait_for_stopped()
 
-        response = self.dap_server.request_unknown()
+        response = self.dap_server.request_custom("unknown")
         self.assertFalse(response["success"])
         self.assertEqual(response["body"]["error"]["format"], "Unknown request")
 
-        self.continue_to_exit()
+        self.continue_to_exit()
\ No newline at end of file
diff --git a/lldb/test/API/tools/lldb-dap/custom/main.c b/lldb/test/API/tools/lldb-dap/custom/main.c
new file mode 100644
index 0000000000000..092333773d0b6
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/custom/main.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int main() {
+  printf("Hello, World!\n");
+  return 0;
+}
diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp
index 0a0d3c3903409..4110432c4fd00 100644
--- a/lldb/tools/lldb-dap/DAP.cpp
+++ b/lldb/tools/lldb-dap/DAP.cpp
@@ -849,10 +849,12 @@ bool DAP::HandleObject(const Message &M) {
     auto handler_pos = request_handlers.find(req->command);
     dispatcher.Set("client_data",
                    llvm::Twine("request_command:", req->command).str());
-    if (handler_pos != request_handlers.end())
+    if (handler_pos != request_handlers.end()) {
       handler_pos->second->Run(*req);
-    else
-      unknown_request_handler->Run(*req);
+    } else {
+      UnknownRequestHandler handler(*this);
+      handler.BaseRequestHandler::Run(*req);
+    }
     return true; // Success
   }
 
@@ -1573,8 +1575,6 @@ void DAP::RegisterRequests() {
   RegisterRequest<VariablesRequestHandler>();
   RegisterRequest<WriteMemoryRequestHandler>();
 
-  unknown_request_handler = std::make_unique<UnknownRequestHandler>(*this);
-
   // Custom requests
   RegisterRequest<CompileUnitsRequestHandler>();
   RegisterRequest<ModulesRequestHandler>();
diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h
index f2e1162eb3a61..34d6a29b3c110 100644
--- a/lldb/tools/lldb-dap/DAP.h
+++ b/lldb/tools/lldb-dap/DAP.h
@@ -482,8 +482,6 @@ struct DAP final : public DAPTransport::MessageHandler {
   llvm::StringMap<std::unique_ptr<BaseRequestHandler>> request_handlers;
   /// @}
 
-  std::unique_ptr<BaseRequestHandler> unknown_request_handler;
-
   /// Event threads.
   /// @{
   void ProgressEventThread();

>From 6d045c19d70caf5882b0daf9fd3fa9dcd548d715 Mon Sep 17 00:00:00 2001
From: Sergei Druzhkov <serzhdruzhok at gmail.com>
Date: Thu, 12 Feb 2026 19:52:07 +0300
Subject: [PATCH 3/5] Update tests

---
 .../tools/lldb-dap/{custom => unknown}/Makefile  |  0
 .../TestDAP_unknownRequest.py                    | 16 ++++++++++++++--
 .../tools/lldb-dap/{custom => unknown}/main.c    |  0
 3 files changed, 14 insertions(+), 2 deletions(-)
 rename lldb/test/API/tools/lldb-dap/{custom => unknown}/Makefile (100%)
 rename lldb/test/API/tools/lldb-dap/{custom => unknown}/TestDAP_unknownRequest.py (53%)
 rename lldb/test/API/tools/lldb-dap/{custom => unknown}/main.c (100%)

diff --git a/lldb/test/API/tools/lldb-dap/custom/Makefile b/lldb/test/API/tools/lldb-dap/unknown/Makefile
similarity index 100%
rename from lldb/test/API/tools/lldb-dap/custom/Makefile
rename to lldb/test/API/tools/lldb-dap/unknown/Makefile
diff --git a/lldb/test/API/tools/lldb-dap/custom/TestDAP_unknownRequest.py b/lldb/test/API/tools/lldb-dap/unknown/TestDAP_unknownRequest.py
similarity index 53%
rename from lldb/test/API/tools/lldb-dap/custom/TestDAP_unknownRequest.py
rename to lldb/test/API/tools/lldb-dap/unknown/TestDAP_unknownRequest.py
index ff38f0188a986..ade02fe000be8 100644
--- a/lldb/test/API/tools/lldb-dap/custom/TestDAP_unknownRequest.py
+++ b/lldb/test/API/tools/lldb-dap/unknown/TestDAP_unknownRequest.py
@@ -11,7 +11,7 @@ class TestDAP_unknown_request(lldbdap_testcase.DAPTestCaseBase):
     Tests handling of unknown request.
     """
 
-    def test(self):
+    def test_no_arguments(self):
         program = self.getBuildArtifact("a.out")
         self.build_and_launch(program, stopOnEntry=True)
         self.dap_server.request_configurationDone()
@@ -21,4 +21,16 @@ def test(self):
         self.assertFalse(response["success"])
         self.assertEqual(response["body"]["error"]["format"], "Unknown request")
 
-        self.continue_to_exit()
\ No newline at end of file
+        self.continue_to_exit()
+
+    def test_with_arguments(self):
+        program = self.getBuildArtifact("a.out")
+        self.build_and_launch(program, stopOnEntry=True)
+        self.dap_server.request_configurationDone()
+        self.dap_server.wait_for_stopped()
+
+        response = self.dap_server.request_custom("unknown", {"foo": "bar", "id": 42})
+        self.assertFalse(response["success"])
+        self.assertEqual(response["body"]["error"]["format"], "Unknown request")
+
+        self.continue_to_exit()
diff --git a/lldb/test/API/tools/lldb-dap/custom/main.c b/lldb/test/API/tools/lldb-dap/unknown/main.c
similarity index 100%
rename from lldb/test/API/tools/lldb-dap/custom/main.c
rename to lldb/test/API/tools/lldb-dap/unknown/main.c

>From 2da1408dfd7748cb88384e80295b282d5dddf952 Mon Sep 17 00:00:00 2001
From: Sergei Druzhkov <serzhdruzhok at gmail.com>
Date: Thu, 12 Feb 2026 20:47:51 +0300
Subject: [PATCH 4/5] Cleanup tests

---
 lldb/test/API/tools/lldb-dap/unknown/TestDAP_unknownRequest.py | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/lldb/test/API/tools/lldb-dap/unknown/TestDAP_unknownRequest.py b/lldb/test/API/tools/lldb-dap/unknown/TestDAP_unknownRequest.py
index ade02fe000be8..5c4b8fe4643a2 100644
--- a/lldb/test/API/tools/lldb-dap/unknown/TestDAP_unknownRequest.py
+++ b/lldb/test/API/tools/lldb-dap/unknown/TestDAP_unknownRequest.py
@@ -1,8 +1,7 @@
 """
-Test lldb-dap custom request.
+Test lldb-dap unknown request.
 """
 
-from lldbsuite.test.decorators import expectedFailureWindows
 import lldbdap_testcase
 
 

>From c9f6aede304c19445272cbd31b2652f8dd836f75 Mon Sep 17 00:00:00 2001
From: Sergei Druzhkov <serzhdruzhok at gmail.com>
Date: Fri, 13 Feb 2026 11:17:42 +0300
Subject: [PATCH 5/5] Fix spelling

---
 .../test/API/tools/lldb-dap/unknown/TestDAP_unknownRequest.py | 4 ++--
 lldb/tools/lldb-dap/Handler/UnknownRequestHandler.cpp         | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/lldb/test/API/tools/lldb-dap/unknown/TestDAP_unknownRequest.py b/lldb/test/API/tools/lldb-dap/unknown/TestDAP_unknownRequest.py
index 5c4b8fe4643a2..8f7b518bb0286 100644
--- a/lldb/test/API/tools/lldb-dap/unknown/TestDAP_unknownRequest.py
+++ b/lldb/test/API/tools/lldb-dap/unknown/TestDAP_unknownRequest.py
@@ -18,7 +18,7 @@ def test_no_arguments(self):
 
         response = self.dap_server.request_custom("unknown")
         self.assertFalse(response["success"])
-        self.assertEqual(response["body"]["error"]["format"], "Unknown request")
+        self.assertEqual(response["body"]["error"]["format"], "unknown request")
 
         self.continue_to_exit()
 
@@ -30,6 +30,6 @@ def test_with_arguments(self):
 
         response = self.dap_server.request_custom("unknown", {"foo": "bar", "id": 42})
         self.assertFalse(response["success"])
-        self.assertEqual(response["body"]["error"]["format"], "Unknown request")
+        self.assertEqual(response["body"]["error"]["format"], "unknown request")
 
         self.continue_to_exit()
diff --git a/lldb/tools/lldb-dap/Handler/UnknownRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/UnknownRequestHandler.cpp
index c576256a48265..0acb7c3dce5bd 100644
--- a/lldb/tools/lldb-dap/Handler/UnknownRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/UnknownRequestHandler.cpp
@@ -15,5 +15,5 @@ using namespace lldb_dap;
 using namespace lldb_dap::protocol;
 
 llvm::Error UnknownRequestHandler::Run(const UnknownArguments &args) const {
-  return llvm::make_error<DAPError>("Unknown request");
+  return llvm::make_error<DAPError>("unknown request");
 }



More information about the lldb-commits mailing list