Browse Source

inspector: make sure all messages are dispatched

This fixes a race condition when messages are coming while V8 is still
dispatching the previous batch.

PR-URL: https://github.com/nodejs/node/pull/8264
Reviewed-By: bnoordhuis - Ben Noordhuis <info@bnoordhuis.nl>
v6.x
Eugene Ostroukhov 9 years ago
committed by Jeremiah Senkpiel
parent
commit
13a522ac39
  1. 16
      src/inspector_agent.cc

16
src/inspector_agent.cc

@ -197,7 +197,7 @@ class AgentImpl {
void SetConnected(bool connected); void SetConnected(bool connected);
void DispatchMessages(); void DispatchMessages();
void Write(int session_id, const String16& message); void Write(int session_id, const String16& message);
void AppendMessage(MessageQueue* vector, int session_id, bool AppendMessage(MessageQueue* vector, int session_id,
const String16& message); const String16& message);
void SwapBehindLock(MessageQueue* vector1, MessageQueue* vector2); void SwapBehindLock(MessageQueue* vector1, MessageQueue* vector2);
void PostIncomingMessage(const String16& message); void PostIncomingMessage(const String16& message);
@ -666,10 +666,12 @@ void AgentImpl::WorkerRunIO() {
CHECK_EQ(err, 0); CHECK_EQ(err, 0);
} }
void AgentImpl::AppendMessage(MessageQueue* queue, int session_id, bool AgentImpl::AppendMessage(MessageQueue* queue, int session_id,
const String16& message) { const String16& message) {
Mutex::ScopedLock scoped_lock(queue_lock_); Mutex::ScopedLock scoped_lock(queue_lock_);
bool trigger_pumping = queue->empty();
queue->push_back(std::make_pair(session_id, message)); queue->push_back(std::make_pair(session_id, message));
return trigger_pumping;
} }
void AgentImpl::SwapBehindLock(MessageQueue* vector1, MessageQueue* vector2) { void AgentImpl::SwapBehindLock(MessageQueue* vector1, MessageQueue* vector2) {
@ -678,13 +680,14 @@ void AgentImpl::SwapBehindLock(MessageQueue* vector1, MessageQueue* vector2) {
} }
void AgentImpl::PostIncomingMessage(const String16& message) { void AgentImpl::PostIncomingMessage(const String16& message) {
AppendMessage(&incoming_message_queue_, frontend_session_id_, message); if (AppendMessage(&incoming_message_queue_, frontend_session_id_, message)) {
v8::Isolate* isolate = parent_env_->isolate(); v8::Isolate* isolate = parent_env_->isolate();
platform_->CallOnForegroundThread(isolate, platform_->CallOnForegroundThread(isolate,
new DispatchOnInspectorBackendTask(this)); new DispatchOnInspectorBackendTask(this));
isolate->RequestInterrupt(InterruptCallback, this); isolate->RequestInterrupt(InterruptCallback, this);
uv_async_send(data_written_); uv_async_send(data_written_);
} }
}
void AgentImpl::OnInspectorConnectionIO(inspector_socket_t* socket) { void AgentImpl::OnInspectorConnectionIO(inspector_socket_t* socket) {
if (client_socket_) { if (client_socket_) {
@ -698,10 +701,16 @@ void AgentImpl::OnInspectorConnectionIO(inspector_socket_t* socket) {
} }
void AgentImpl::DispatchMessages() { void AgentImpl::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_) if (dispatching_messages_)
return; return;
dispatching_messages_ = true; dispatching_messages_ = true;
MessageQueue tasks; MessageQueue tasks;
do {
tasks.clear();
SwapBehindLock(&incoming_message_queue_, &tasks); SwapBehindLock(&incoming_message_queue_, &tasks);
for (const MessageQueue::value_type& pair : tasks) { for (const MessageQueue::value_type& pair : tasks) {
const String16& message = pair.second; const String16& message = pair.second;
@ -725,6 +734,7 @@ void AgentImpl::DispatchMessages() {
inspector_->dispatchMessageFromFrontend(message); inspector_->dispatchMessageFromFrontend(message);
} }
} }
} while (!tasks.empty());
uv_async_send(data_written_); uv_async_send(data_written_);
dispatching_messages_ = false; dispatching_messages_ = false;
} }

Loading…
Cancel
Save