diff options
author | Eugene Ostroukhov <eostroukhov@chromium.org> | 2018-04-24 11:16:55 -0700 |
---|---|---|
committer | Eugene Ostroukhov <eostroukhov@google.com> | 2018-04-26 12:48:48 -0700 |
commit | 13001035340d6d3fb173fef4a1db42ba70f61720 (patch) | |
tree | 7333699fc80f90725a00b229dccc5bf718cfea78 /src/inspector_io.cc | |
parent | 5c57cea8049bad5939807e6b849ee303ec8e1526 (diff) | |
download | node-new-13001035340d6d3fb173fef4a1db42ba70f61720.tar.gz |
inspector: allow concurrent inspector sessions
This change enables concurrent inspector sessions, through WebSocket
interface as well as JS interface, in any combination.
PR-URL: https://github.com/nodejs/node/pull/20137
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Diffstat (limited to 'src/inspector_io.cc')
-rw-r--r-- | src/inspector_io.cc | 74 |
1 files changed, 31 insertions, 43 deletions
diff --git a/src/inspector_io.cc b/src/inspector_io.cc index 01ddc296b0..5e0d29d3ca 100644 --- a/src/inspector_io.cc +++ b/src/inspector_io.cc @@ -122,11 +122,11 @@ std::unique_ptr<StringBuffer> Utf8ToStringView(const std::string& message) { class IoSessionDelegate : public InspectorSessionDelegate { public: - explicit IoSessionDelegate(InspectorIo* io) : io_(io) { } - bool WaitForFrontendMessageWhilePaused() override; + explicit IoSessionDelegate(InspectorIo* io, int id) : io_(io), id_(id) { } void SendMessageToFrontend(const v8_inspector::StringView& message) override; private: InspectorIo* io_; + int id_; }; // Passed to InspectorSocketServer to handle WS inspector protocol events, @@ -190,8 +190,7 @@ InspectorIo::InspectorIo(Environment* env, v8::Platform* platform, : options_(options), thread_(), delegate_(nullptr), state_(State::kNew), parent_env_(env), thread_req_(), platform_(platform), - dispatching_messages_(false), session_id_(0), - script_name_(path), + dispatching_messages_(false), script_name_(path), wait_for_connect_(wait_for_connect), port_(-1) { main_thread_req_ = new AsyncAndAgent({uv_async_t(), env->inspector_agent()}); CHECK_EQ(0, uv_async_init(env->event_loop(), &main_thread_req_->first, @@ -222,7 +221,7 @@ bool InspectorIo::Start() { } void InspectorIo::Stop() { - CHECK(state_ == State::kAccepting || state_ == State::kConnected); + CHECK(state_ == State::kAccepting || !sessions_.empty()); Write(TransportAction::kKill, 0, StringView()); int err = uv_thread_join(&thread_); CHECK_EQ(err, 0); @@ -237,12 +236,11 @@ bool InspectorIo::IsStarted() { void InspectorIo::WaitForDisconnect() { if (state_ == State::kAccepting) state_ = State::kDone; - if (state_ == State::kConnected) { + if (!sessions_.empty()) { state_ = State::kShutDown; Write(TransportAction::kStop, 0, StringView()); fprintf(stderr, "Waiting for the debugger to disconnect...\n"); fflush(stderr); - parent_env_->inspector_agent()->RunMessageLoop(); } } @@ -348,45 +346,23 @@ void InspectorIo::PostIncomingMessage(InspectorAction action, int session_id, isolate->RequestInterrupt(InterruptCallback, agent); CHECK_EQ(0, uv_async_send(&main_thread_req_->first)); } - NotifyMessageReceived(); + Mutex::ScopedLock scoped_lock(state_lock_); + incoming_message_cond_.Broadcast(scoped_lock); } std::vector<std::string> InspectorIo::GetTargetIds() const { return delegate_ ? delegate_->GetTargetIds() : std::vector<std::string>(); } -void InspectorIo::WaitForFrontendMessageWhilePaused() { - dispatching_messages_ = false; - Mutex::ScopedLock scoped_lock(state_lock_); - if (incoming_message_queue_.empty()) - incoming_message_cond_.Wait(scoped_lock); -} - -void InspectorIo::NotifyMessageReceived() { - Mutex::ScopedLock scoped_lock(state_lock_); - incoming_message_cond_.Broadcast(scoped_lock); -} - TransportAction InspectorIo::Attach(int session_id) { Agent* agent = parent_env_->inspector_agent(); - if (agent->delegate() != nullptr) - return TransportAction::kDeclineSession; - - CHECK_EQ(session_delegate_, nullptr); - session_id_ = session_id; - state_ = State::kConnected; fprintf(stderr, "Debugger attached.\n"); - session_delegate_ = std::unique_ptr<InspectorSessionDelegate>( - new IoSessionDelegate(this)); - agent->Connect(session_delegate_.get()); + sessions_[session_id] = + agent->Connect(std::make_unique<IoSessionDelegate>(this, session_id)); return TransportAction::kAcceptSession; } void InspectorIo::DispatchMessages() { - // This function can be reentered if there was an incoming message while - // V8 was processing another inspector request (e.g. if the user is - // evaluating a long-running JS code snippet). This can happen only at - // specific points (e.g. the lines that call inspector_ methods) if (dispatching_messages_) return; dispatching_messages_ = true; @@ -409,17 +385,20 @@ void InspectorIo::DispatchMessages() { Attach(id); break; case InspectorAction::kEndSession: - CHECK_NE(session_delegate_, nullptr); + sessions_.erase(id); + if (!sessions_.empty()) + continue; if (state_ == State::kShutDown) { state_ = State::kDone; } else { state_ = State::kAccepting; } - parent_env_->inspector_agent()->Disconnect(); - session_delegate_.reset(); break; case InspectorAction::kSendMessage: - parent_env_->inspector_agent()->Dispatch(message); + auto session = sessions_.find(id); + if (session != sessions_.end() && session->second) { + session->second->Dispatch(message); + } break; } } @@ -445,6 +424,20 @@ void InspectorIo::Write(TransportAction action, int session_id, CHECK_EQ(0, err); } +bool InspectorIo::WaitForFrontendEvent() { + // We allow DispatchMessages reentry as we enter the pause. This is important + // to support debugging the code invoked by an inspector call, such + // as Runtime.evaluate + dispatching_messages_ = false; + Mutex::ScopedLock scoped_lock(state_lock_); + if (sessions_.empty()) + return false; + if (dispatching_message_queue_.empty() && incoming_message_queue_.empty()) { + incoming_message_cond_.Wait(scoped_lock); + } + return true; +} + InspectorIoDelegate::InspectorIoDelegate(InspectorIo* io, const std::string& script_path, const std::string& script_name, @@ -502,14 +495,9 @@ std::string InspectorIoDelegate::GetTargetUrl(const std::string& id) { return "file://" + script_path_; } -bool IoSessionDelegate::WaitForFrontendMessageWhilePaused() { - io_->WaitForFrontendMessageWhilePaused(); - return true; -} - void IoSessionDelegate::SendMessageToFrontend( const v8_inspector::StringView& message) { - io_->Write(TransportAction::kSendMessage, io_->session_id_, message); + io_->Write(TransportAction::kSendMessage, id_, message); } } // namespace inspector |