summaryrefslogtreecommitdiff
path: root/src/inspector_io.cc
diff options
context:
space:
mode:
authorEugene Ostroukhov <eostroukhov@chromium.org>2018-04-24 11:16:55 -0700
committerEugene Ostroukhov <eostroukhov@google.com>2018-04-26 12:48:48 -0700
commit13001035340d6d3fb173fef4a1db42ba70f61720 (patch)
tree7333699fc80f90725a00b229dccc5bf718cfea78 /src/inspector_io.cc
parent5c57cea8049bad5939807e6b849ee303ec8e1526 (diff)
downloadnode-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.cc74
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