14
14
#include " LLDBUtils.h"
15
15
#include " OutputRedirector.h"
16
16
#include " Protocol/ProtocolBase.h"
17
+ #include " Protocol/ProtocolRequests.h"
17
18
#include " Protocol/ProtocolTypes.h"
18
19
#include " Transport.h"
19
20
#include " lldb/API/SBBreakpoint.h"
40
41
#include < algorithm>
41
42
#include < cassert>
42
43
#include < chrono>
44
+ #include < condition_variable>
43
45
#include < cstdarg>
44
46
#include < cstdio>
45
47
#include < fstream>
48
+ #include < future>
46
49
#include < memory>
47
50
#include < mutex>
51
+ #include < optional>
48
52
#include < string>
49
53
#include < utility>
54
+ #include < variant>
50
55
51
56
#if defined(_WIN32)
52
57
#define NOMINMAX
58
63
#endif
59
64
60
65
using namespace lldb_dap ;
66
+ using namespace lldb_dap ::protocol;
61
67
62
68
namespace {
63
69
#ifdef _WIN32
@@ -230,7 +236,7 @@ void DAP::StopEventHandlers() {
230
236
void DAP::SendJSON (const llvm::json::Value &json) {
231
237
// FIXME: Instead of parsing the output message from JSON, pass the `Message`
232
238
// as parameter to `SendJSON`.
233
- protocol:: Message message;
239
+ Message message;
234
240
llvm::json::Path::Root root;
235
241
if (!fromJSON (json, message, root)) {
236
242
DAP_LOG_ERROR (log, root.getError (), " ({1}) encoding failed: {0}" ,
@@ -240,7 +246,27 @@ void DAP::SendJSON(const llvm::json::Value &json) {
240
246
Send (message);
241
247
}
242
248
243
- void DAP::Send (const protocol::Message &message) {
249
+ void DAP::Send (const Message &message) {
250
+ // FIXME: After all the requests have migrated from LegacyRequestHandler >
251
+ // RequestHandler<> this should be handled in RequestHandler<>::operator().
252
+ if (auto *resp = std::get_if<Response>(&message);
253
+ resp && debugger.InterruptRequested ()) {
254
+ // Clear the interrupt request.
255
+ debugger.CancelInterruptRequest ();
256
+
257
+ // If the debugger was interrupted, convert this response into a 'cancelled'
258
+ // response because we might have a partial result.
259
+ Response cancelled{/* request_seq=*/ resp->request_seq ,
260
+ /* command=*/ resp->command ,
261
+ /* success=*/ false ,
262
+ /* message=*/ eResponseMessageCancelled,
263
+ /* body=*/ std::nullopt};
264
+ if (llvm::Error err = transport.Write (cancelled))
265
+ DAP_LOG_ERROR (log, std::move (err), " ({1}) write failed: {0}" ,
266
+ transport.GetClientName ());
267
+ return ;
268
+ }
269
+
244
270
if (llvm::Error err = transport.Write (message))
245
271
DAP_LOG_ERROR (log, std::move (err), " ({1}) write failed: {0}" ,
246
272
transport.GetClientName ());
@@ -675,11 +701,25 @@ void DAP::SetTarget(const lldb::SBTarget target) {
675
701
}
676
702
}
677
703
678
- bool DAP::HandleObject (const protocol::Message &M) {
679
- if (const auto *req = std::get_if<protocol::Request>(&M)) {
704
+ bool DAP::HandleObject (const Message &M) {
705
+ if (const auto *req = std::get_if<Request>(&M)) {
706
+ {
707
+ std::lock_guard<std::mutex> guard (m_active_request_mutex);
708
+ m_active_request = req;
709
+
710
+ // Clear the interrupt request prior to invoking a handler.
711
+ if (debugger.InterruptRequested ())
712
+ debugger.CancelInterruptRequest ();
713
+ }
714
+
715
+ auto cleanup = llvm::make_scope_exit ([&]() {
716
+ std::scoped_lock<std::mutex> active_request_lock (m_active_request_mutex);
717
+ m_active_request = nullptr ;
718
+ });
719
+
680
720
auto handler_pos = request_handlers.find (req->command );
681
721
if (handler_pos != request_handlers.end ()) {
682
- (* handler_pos->second ) (*req);
722
+ handler_pos->second -> Run (*req);
683
723
return true ; // Success
684
724
}
685
725
@@ -688,10 +728,10 @@ bool DAP::HandleObject(const protocol::Message &M) {
688
728
return false ; // Fail
689
729
}
690
730
691
- if (const auto *resp = std::get_if<protocol:: Response>(&M)) {
731
+ if (const auto *resp = std::get_if<Response>(&M)) {
692
732
std::unique_ptr<ResponseHandler> response_handler;
693
733
{
694
- std::lock_guard<std::mutex> locker (call_mutex);
734
+ std::lock_guard<std::mutex> guard (call_mutex);
695
735
auto inflight = inflight_reverse_requests.find (resp->request_seq );
696
736
if (inflight != inflight_reverse_requests.end ()) {
697
737
response_handler = std::move (inflight->second );
@@ -782,28 +822,121 @@ llvm::Error DAP::Disconnect(bool terminateDebuggee) {
782
822
return ToError (error);
783
823
}
784
824
825
+ bool DAP::IsCancelled (const protocol::Request &req) {
826
+ std::lock_guard<std::mutex> guard (m_cancelled_requests_mutex);
827
+ return m_cancelled_requests.contains (req.seq );
828
+ }
829
+
830
+ void DAP::ClearCancelRequest (const CancelArguments &args) {
831
+ std::lock_guard<std::mutex> guard (m_cancelled_requests_mutex);
832
+ if (args.requestId )
833
+ m_cancelled_requests.erase (*args.requestId );
834
+ }
835
+
836
+ template <typename T>
837
+ static std::optional<T> getArgumentsIfRequest (const Message &pm,
838
+ llvm::StringLiteral command) {
839
+ auto *const req = std::get_if<Request>(&pm);
840
+ if (!req || req->command != command)
841
+ return std::nullopt;
842
+
843
+ T args;
844
+ llvm::json::Path::Root root;
845
+ if (!fromJSON (req->arguments , args, root)) {
846
+ return std::nullopt;
847
+ }
848
+
849
+ return std::move (args);
850
+ }
851
+
785
852
llvm::Error DAP::Loop () {
786
- auto cleanup = llvm::make_scope_exit ([this ]() {
853
+ std::future<llvm::Error> queue_reader =
854
+ std::async (std::launch::async, [&]() -> llvm::Error {
855
+ llvm::set_thread_name (transport.GetClientName () + " .transport_handler" );
856
+ auto cleanup = llvm::make_scope_exit ([&]() {
857
+ // Ensure we're marked as disconnecting when the reader exits.
858
+ disconnecting = true ;
859
+ m_queue_cv.notify_all ();
860
+ });
861
+
862
+ while (!disconnecting) {
863
+ llvm::Expected<Message> next =
864
+ transport.Read (std::chrono::seconds (1 ));
865
+ if (next.errorIsA <EndOfFileError>()) {
866
+ consumeError (next.takeError ());
867
+ break ;
868
+ }
869
+
870
+ // If the read timed out, continue to check if we should disconnect.
871
+ if (next.errorIsA <TimeoutError>()) {
872
+ consumeError (next.takeError ());
873
+ continue ;
874
+ }
875
+
876
+ if (llvm::Error err = next.takeError ())
877
+ return err;
878
+
879
+ if (const protocol::Request *req =
880
+ std::get_if<protocol::Request>(&*next);
881
+ req && req->command == " disconnect" ) {
882
+ disconnecting = true ;
883
+ }
884
+
885
+ const std::optional<CancelArguments> cancel_args =
886
+ getArgumentsIfRequest<CancelArguments>(*next, " cancel" );
887
+ if (cancel_args) {
888
+ {
889
+ std::lock_guard<std::mutex> guard (m_cancelled_requests_mutex);
890
+ if (cancel_args->requestId )
891
+ m_cancelled_requests.insert (*cancel_args->requestId );
892
+ }
893
+
894
+ // If a cancel is requested for the active request, make a best
895
+ // effort attempt to interrupt.
896
+ std::lock_guard<std::mutex> guard (m_active_request_mutex);
897
+ if (m_active_request &&
898
+ cancel_args->requestId == m_active_request->seq ) {
899
+ DAP_LOG (
900
+ log,
901
+ " ({0}) interrupting inflight request (command={1} seq={2})" ,
902
+ transport.GetClientName (), m_active_request->command ,
903
+ m_active_request->seq );
904
+ debugger.RequestInterrupt ();
905
+ }
906
+ }
907
+
908
+ {
909
+ std::lock_guard<std::mutex> guard (m_queue_mutex);
910
+ m_queue.push_back (std::move (*next));
911
+ }
912
+ m_queue_cv.notify_one ();
913
+ }
914
+
915
+ return llvm::Error::success ();
916
+ });
917
+
918
+ auto cleanup = llvm::make_scope_exit ([&]() {
787
919
out.Stop ();
788
920
err.Stop ();
789
921
StopEventHandlers ();
790
922
});
923
+
791
924
while (!disconnecting) {
792
- llvm::Expected<std::optional<protocol::Message>> next = transport.Read ();
793
- if (!next)
794
- return next.takeError ();
925
+ std::unique_lock<std::mutex> lock (m_queue_mutex);
926
+ m_queue_cv.wait (lock, [&] { return disconnecting || !m_queue.empty (); });
795
927
796
- // nullopt on EOF
797
- if (!*next)
928
+ if (m_queue.empty ())
798
929
break ;
799
930
800
- if (!HandleObject (**next)) {
931
+ Message next = m_queue.front ();
932
+ m_queue.pop_front ();
933
+
934
+ if (!HandleObject (next))
801
935
return llvm::createStringError (llvm::inconvertibleErrorCode (),
802
936
" unhandled packet" );
803
- }
804
937
}
805
938
806
- return llvm::Error::success ();
939
+ return queue_reader. get ();
807
940
}
808
941
809
942
lldb::SBError DAP::WaitForProcessToStop (uint32_t seconds) {
@@ -1128,8 +1261,8 @@ lldb::SBValue Variables::FindVariable(uint64_t variablesReference,
1128
1261
}
1129
1262
}
1130
1263
} else {
1131
- // This is not under the globals or locals scope, so there are no duplicated
1132
- // names.
1264
+ // This is not under the globals or locals scope, so there are no
1265
+ // duplicated names.
1133
1266
1134
1267
// We have a named item within an actual variable so we need to find it
1135
1268
// withing the container variable by name.
0 commit comments