| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 5a2ce36 commit 989a2a1
1 file changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -17,6 +17,7 @@ | |||
| 17 | 17 | #include "libplatform/libplatform.h" | |
| 18 | 18 | ||
| 19 | 19 | #include <string.h> | |
| 20 | + #include <utility> | ||
| 20 | 21 | #include <vector> | |
| 21 | 22 | ||
| 22 | 23 | // We need pid to use as ID with Chrome | |
@@ -31,6 +32,9 @@ | |||
| 31 | 32 | namespace node { | |
| 32 | 33 | namespace { | |
| 33 | 34 | ||
| 35 | + const char TAG_CONNECT[] = "#connect"; | ||
| 36 | + const char TAG_DISCONNECT[] = "#disconnect"; | ||
| 37 | + | ||
| 34 | 38 | const char DEVTOOLS_PATH[] = "/node"; | |
| 35 | 39 | const char DEVTOOLS_HASH[] = "521e5b7e2b7cc66b4006a8a54cb9c4e57494a5ef"; | |
| 36 | 40 | ||
@@ -154,7 +158,6 @@ bool RespondToGet(inspector_socket_t* socket, const char* path, int port) { | |||
| 154 | 158 | namespace inspector { | |
| 155 | 159 | ||
| 156 | 160 | using blink::protocol::DictionaryValue; | |
| 157 | - using blink::protocol::String16; | ||
| 158 | 161 | ||
| 159 | 162 | class AgentImpl { | |
| 160 | 163 | public: | |
@@ -171,24 +174,27 @@ class AgentImpl { | |||
| 171 | 174 | void WaitForDisconnect(); | |
| 172 | 175 | ||
| 173 | 176 | private: | |
| 177 | + using MessageQueue = std::vector<std::pair<int, String16>>; | ||
| 178 | + | ||
| 174 | 179 | static void ThreadCbIO(void* agent); | |
| 175 | 180 | static void OnSocketConnectionIO(uv_stream_t* server, int status); | |
| 176 | 181 | static bool OnInspectorHandshakeIO(inspector_socket_t* socket, | |
| 177 | 182 | enum inspector_handshake_event state, | |
| 178 | 183 | const char* path); | |
| 179 | - static void OnRemoteDataIO(uv_stream_t* stream, ssize_t read, | ||
| 180 | - const uv_buf_t* b); | ||
| 181 | 184 | static void WriteCbIO(uv_async_t* async); | |
| 182 | 185 | ||
| 183 | 186 | void WorkerRunIO(); | |
| 184 | 187 | void OnInspectorConnectionIO(inspector_socket_t* socket); | |
| 185 | - void PushPendingMessage(std::vector<std::string>* queue, | ||
| 186 | - const std::string& message); | ||
| 187 | - void SwapBehindLock(std::vector<std::string> AgentImpl::*queue, | ||
| 188 | - std::vector<std::string>* output); | ||
| 188 | + void OnRemoteDataIO(inspector_socket_t* stream, ssize_t read, | ||
| 189 | + const uv_buf_t* b); | ||
| 189 | 190 | void PostMessages(); | |
| 190 | 191 | void SetConnected(bool connected); | |
| 191 | - void Write(const std::string& message); | ||
| 192 | + void DispatchMessages(); | ||
| 193 | + void Write(int session_id, const String16& message); | ||
| 194 | + void AppendMessage(MessageQueue* vector, int session_id, | ||
| 195 | + const String16& message); | ||
| 196 | + void SwapBehindLock(MessageQueue* vector1, MessageQueue* vector2); | ||
| 197 | + void PostIncomingMessage(const String16& message); | ||
| 192 | 198 | ||
| 193 | 199 | uv_sem_t start_sem_; | |
| 194 | 200 | ConditionVariable pause_cond_; | |
@@ -208,27 +214,36 @@ class AgentImpl { | |||
| 208 | 214 | inspector_socket_t* client_socket_; | |
| 209 | 215 | blink::V8Inspector* inspector_; | |
| 210 | 216 | v8::Platform* platform_; | |
| 211 | - std::vector<std::string> message_queue_; | ||
| 212 | - std::vector<std::string> outgoing_message_queue_; | ||
| 217 | + MessageQueue incoming_message_queue_; | ||
| 218 | + MessageQueue outgoing_message_queue_; | ||
| 213 | 219 | bool dispatching_messages_; | |
| 220 | + int frontend_session_id_; | ||
| 221 | + int backend_session_id_; | ||
| 214 | 222 | ||
| 215 | 223 | friend class ChannelImpl; | |
| 216 | 224 | friend class DispatchOnInspectorBackendTask; | |
| 217 | 225 | friend class SetConnectedTask; | |
| 218 | 226 | friend class V8NodeInspector; | |
| 219 | 227 | friend void InterruptCallback(v8::Isolate*, void* agent); | |
| 228 | + friend void DataCallback(uv_stream_t* stream, ssize_t read, | ||
| 229 | + const uv_buf_t* buf); | ||
| 220 | 230 | }; | |
| 221 | 231 | ||
| 222 | 232 | void InterruptCallback(v8::Isolate*, void* agent) { | |
| 223 | - static_cast<AgentImpl*>(agent)->PostMessages(); | ||
| 233 | + static_cast<AgentImpl*>(agent)->DispatchMessages(); | ||
| 234 | + } | ||
| 235 | + | ||
| 236 | + void DataCallback(uv_stream_t* stream, ssize_t read, const uv_buf_t* buf) { | ||
| 237 | + inspector_socket_t* socket = static_cast<inspector_socket_t*>(stream->data); | ||
| 238 | + static_cast<AgentImpl*>(socket->data)->OnRemoteDataIO(socket, read, buf); | ||
| 224 | 239 | } | |
| 225 | 240 | ||
| 226 | 241 | class DispatchOnInspectorBackendTask : public v8::Task { | |
| 227 | 242 | public: | |
| 228 | 243 | explicit DispatchOnInspectorBackendTask(AgentImpl* agent) : agent_(agent) {} | |
| 229 | 244 | ||
| 230 | 245 | void Run() override { | |
| 231 | - agent_->PostMessages(); | ||
| 246 | + agent_->DispatchMessages(); | ||
| 232 | 247 | } | |
| 233 | 248 | ||
| 234 | 249 | private: | |
@@ -251,27 +266,12 @@ class ChannelImpl final : public blink::protocol::FrontendChannel { | |||
| 251 | 266 | void flushProtocolNotifications() override { } | |
| 252 | 267 | ||
| 253 | 268 | void sendMessageToFrontend(const String16& message) { | |
| 254 | - agent_->Write(message.utf8()); | ||
| 269 | + agent_->Write(agent_->frontend_session_id_, message); | ||
| 255 | 270 | } | |
| 256 | 271 | ||
| 257 | 272 | AgentImpl* const agent_; | |
| 258 | 273 | }; | |
| 259 | 274 | ||
| 260 | - class SetConnectedTask : public v8::Task { | ||
| 261 | - public: | ||
| 262 | - SetConnectedTask(AgentImpl* agent, bool connected) | ||
| 263 | - : agent_(agent), | ||
| 264 | - connected_(connected) {} | ||
| 265 | - | ||
| 266 | - void Run() override { | ||
| 267 | - agent_->SetConnected(connected_); | ||
| 268 | - } | ||
| 269 | - | ||
| 270 | - private: | ||
| 271 | - AgentImpl* agent_; | ||
| 272 | - bool connected_; | ||
| 273 | - }; | ||
| 274 | - | ||
| 275 | 275 | class V8NodeInspector : public blink::V8Inspector { | |
| 276 | 276 | public: | |
| 277 | 277 | V8NodeInspector(AgentImpl* agent, node::Environment* env, | |
@@ -320,7 +320,9 @@ AgentImpl::AgentImpl(Environment* env) : port_(0), | |||
| 320 | 320 | client_socket_(nullptr), | |
| 321 | 321 | inspector_(nullptr), | |
| 322 | 322 | platform_(nullptr), | |
| 323 | - dispatching_messages_(false) { | ||
| 323 | + dispatching_messages_(false), | ||
| 324 | + frontend_session_id_(0), | ||
| 325 | + backend_session_id_(0) { | ||
| 324 | 326 | CHECK_EQ(0, uv_sem_init(&start_sem_, 0)); | |
| 325 | 327 | memset(&data_written_, 0, sizeof(data_written_)); | |
| 326 | 328 | memset(&io_thread_req_, 0, sizeof(io_thread_req_)); | |
@@ -355,10 +357,7 @@ void AgentImpl::Start(v8::Platform* platform, int port, bool wait) { | |||
| 355 | 357 | uv_sem_wait(&start_sem_); | |
| 356 | 358 | ||
| 357 | 359 | if (wait) { | |
| 358 | - // Flush messages in case of wait to connect, see OnRemoteDataIO on how it | ||
| 359 | - // should be fixed. | ||
| 360 | - SetConnected(true); | ||
| 361 | - PostMessages(); | ||
| 360 | + DispatchMessages(); | ||
| 362 | 361 | } | |
| 363 | 362 | } | |
| 364 | 363 | ||
@@ -424,67 +423,54 @@ bool AgentImpl::OnInspectorHandshakeIO(inspector_socket_t* socket, | |||
| 424 | 423 | } | |
| 425 | 424 | } | |
| 426 | 425 | ||
| 427 | - // static | ||
| 428 | - void AgentImpl::OnRemoteDataIO(uv_stream_t* stream, | ||
| 429 | - ssize_t read, | ||
| 430 | - const uv_buf_t* b) { | ||
| 431 | - inspector_socket_t* socket = static_cast<inspector_socket_t*>(stream->data); | ||
| 432 | - AgentImpl* agent = static_cast<AgentImpl*>(socket->data); | ||
| 433 | - Mutex::ScopedLock scoped_lock(agent->pause_lock_); | ||
| 426 | + void AgentImpl::OnRemoteDataIO(inspector_socket_t* socket, | ||
| 427 | + ssize_t read, | ||
| 428 | + const uv_buf_t* buf) { | ||
| 429 | + Mutex::ScopedLock scoped_lock(pause_lock_); | ||
| 434 | 430 | if (read > 0) { | |
| 435 | - std::string str(b->base, read); | ||
| 436 | - agent->PushPendingMessage(&agent->message_queue_, str); | ||
| 437 | - free(b->base); | ||
| 438 | - | ||
| 431 | + String16 str = String16::fromUTF8(buf->base, read); | ||
| 432 | + PostIncomingMessage(str); | ||
| 439 | 433 | // TODO(pfeldman): Instead of blocking execution while debugger | |
| 440 | 434 | // engages, node should wait for the run callback from the remote client | |
| 441 | 435 | // and initiate its startup. This is a change to node.cc that should be | |
| 442 | 436 | // upstreamed separately. | |
| 443 | - if (agent->wait_ && str.find("\"Runtime.run\"") != std::string::npos) { | ||
| 444 | - agent->wait_ = false; | ||
| 445 | - uv_sem_post(&agent->start_sem_); | ||
| 437 | + if (wait_ && str.find("\"Runtime.run\"") != std::string::npos) { | ||
| 438 | + wait_ = false; | ||
| 439 | + uv_sem_post(&start_sem_); | ||
| 446 | 440 | } | |
| 447 | 441 | ||
| 448 | - agent->platform_->CallOnForegroundThread(agent->parent_env_->isolate(), | ||
| 449 | - new DispatchOnInspectorBackendTask(agent)); | ||
| 450 | - agent->parent_env_->isolate() | ||
| 451 | - ->RequestInterrupt(InterruptCallback, agent); | ||
| 452 | - uv_async_send(&agent->data_written_); | ||
| 442 | + platform_->CallOnForegroundThread(parent_env_->isolate(), | ||
| 443 | + new DispatchOnInspectorBackendTask(this)); | ||
| 444 | + parent_env_->isolate()->RequestInterrupt(InterruptCallback, this); | ||
| 445 | + uv_async_send(&data_written_); | ||
| 453 | 446 | } else if (read <= 0) { | |
| 454 | 447 | // EOF | |
| 455 | - if (agent->client_socket_ == socket) { | ||
| 456 | - agent->client_socket_ = nullptr; | ||
| 457 | - agent->platform_->CallOnForegroundThread(agent->parent_env_->isolate(), | ||
| 458 | - new SetConnectedTask(agent, false)); | ||
| 459 | - uv_async_send(&agent->data_written_); | ||
| 448 | + if (client_socket_ == socket) { | ||
| 449 | + String16 message(TAG_DISCONNECT, sizeof(TAG_DISCONNECT) - 1); | ||
| 450 | + client_socket_ = nullptr; | ||
| 451 | + PostIncomingMessage(message); | ||
| 460 | 452 | } | |
| 461 | 453 | DisconnectAndDisposeIO(socket); | |
| 462 | 454 | } | |
| 463 | - agent->pause_cond_.Broadcast(scoped_lock); | ||
| 464 | - } | ||
| 465 | - | ||
| 466 | - void AgentImpl::PushPendingMessage(std::vector<std::string>* queue, | ||
| 467 | - const std::string& message) { | ||
| 468 | - Mutex::ScopedLock scoped_lock(queue_lock_); | ||
| 469 | - queue->push_back(message); | ||
| 470 | - } | ||
| 471 | - | ||
| 472 | - void AgentImpl::SwapBehindLock(std::vector<std::string> AgentImpl::*queue, | ||
| 473 | - std::vector<std::string>* output) { | ||
| 474 | - Mutex::ScopedLock scoped_lock(queue_lock_); | ||
| 475 | - (this->*queue).swap(*output); | ||
| 455 | + if (buf) { | ||
| 456 | + free(buf->base); | ||
| 457 | + } | ||
| 458 | + pause_cond_.Broadcast(scoped_lock); | ||
| 476 | 459 | } | |
| 477 | 460 | ||
| 478 | 461 | // static | |
| 479 | 462 | void AgentImpl::WriteCbIO(uv_async_t* async) { | |
| 480 | 463 | AgentImpl* agent = static_cast<AgentImpl*>(async->data); | |
| 481 | 464 | inspector_socket_t* socket = agent->client_socket_; | |
| 482 | 465 | if (socket) { | |
| 483 | - std::vector<std::string> outgoing_messages; | ||
| 484 | - agent->SwapBehindLock(&AgentImpl::outgoing_message_queue_, | ||
| 485 | - &outgoing_messages); | ||
| 486 | - for (auto const& message : outgoing_messages) | ||
| 487 | - inspector_write(socket, message.c_str(), message.length()); | ||
| 466 | + MessageQueue outgoing_messages; | ||
| 467 | + agent->SwapBehindLock(&agent->outgoing_message_queue_, &outgoing_messages); | ||
| 468 | + for (const MessageQueue::value_type& outgoing : outgoing_messages) { | ||
| 469 | + if (outgoing.first == agent->frontend_session_id_) { | ||
| 470 | + std::string message = outgoing.second.utf8(); | ||
| 471 | + inspector_write(socket, message.c_str(), message.length()); | ||
| 472 | + } | ||
| 473 | + } | ||
| 488 | 474 | } | |
| 489 | 475 | } | |
| 490 | 476 | ||
@@ -518,49 +504,70 @@ void AgentImpl::WorkerRunIO() { | |||
| 518 | 504 | uv_run(&child_loop_, UV_RUN_DEFAULT); | |
| 519 | 505 | } | |
| 520 | 506 | ||
| 507 | + void AgentImpl::AppendMessage(MessageQueue* queue, int session_id, | ||
| 508 | + const String16& message) { | ||
| 509 | + Mutex::ScopedLock scoped_lock(queue_lock_); | ||
| 510 | + queue->push_back(std::make_pair(session_id, message)); | ||
| 511 | + } | ||
| 512 | + | ||
| 513 | + void AgentImpl::SwapBehindLock(MessageQueue* vector1, MessageQueue* vector2) { | ||
| 514 | + Mutex::ScopedLock scoped_lock(queue_lock_); | ||
| 515 | + vector1->swap(*vector2); | ||
| 516 | + } | ||
| 517 | + | ||
| 518 | + void AgentImpl::PostIncomingMessage(const String16& message) { | ||
| 519 | + AppendMessage(&incoming_message_queue_, frontend_session_id_, message); | ||
| 520 | + v8::Isolate* isolate = parent_env_->isolate(); | ||
| 521 | + platform_->CallOnForegroundThread(isolate, | ||
| 522 | + new DispatchOnInspectorBackendTask(this)); | ||
| 523 | + isolate->RequestInterrupt(InterruptCallback, this); | ||
| 524 | + uv_async_send(&data_written_); | ||
| 525 | + } | ||
| 526 | + | ||
| 521 | 527 | void AgentImpl::OnInspectorConnectionIO(inspector_socket_t* socket) { | |
| 522 | 528 | if (client_socket_) { | |
| 523 | 529 | DisconnectAndDisposeIO(socket); | |
| 524 | 530 | return; | |
| 525 | 531 | } | |
| 526 | 532 | client_socket_ = socket; | |
| 527 | - inspector_read_start(socket, OnBufferAlloc, AgentImpl::OnRemoteDataIO); | ||
| 528 | - platform_->CallOnForegroundThread(parent_env_->isolate(), | ||
| 529 | - new SetConnectedTask(this, true)); | ||
| 533 | + inspector_read_start(socket, OnBufferAlloc, DataCallback); | ||
| 534 | + frontend_session_id_++; | ||
| 535 | + PostIncomingMessage(String16(TAG_CONNECT, sizeof(TAG_CONNECT) - 1)); | ||
| 530 | 536 | } | |
| 531 | 537 | ||
| 532 | - void AgentImpl::PostMessages() { | ||
| 538 | + void AgentImpl::DispatchMessages() { | ||
| 533 | 539 | if (dispatching_messages_) | |
| 534 | 540 | return; | |
| 535 | 541 | dispatching_messages_ = true; | |
| 536 | - std::vector<std::string> messages; | ||
| 537 | - SwapBehindLock(&AgentImpl::message_queue_, &messages); | ||
| 538 | - for (auto const& message : messages) | ||
| 539 | - inspector_->dispatchMessageFromFrontend( | ||
| 540 | - String16::fromUTF8(message.c_str(), message.length())); | ||
| 542 | + MessageQueue tasks; | ||
| 543 | + SwapBehindLock(&incoming_message_queue_, &tasks); | ||
| 544 | + for (const MessageQueue::value_type& pair : tasks) { | ||
| 545 | + const String16& message = pair.second; | ||
| 546 | + if (message == TAG_CONNECT) { | ||
| 547 | + CHECK_EQ(false, connected_); | ||
| 548 | + backend_session_id_++; | ||
| 549 | + connected_ = true; | ||
| 550 | + fprintf(stderr, "Debugger attached.\n"); | ||
| 551 | + inspector_->connectFrontend(new ChannelImpl(this)); | ||
| 552 | + } else if (message == TAG_DISCONNECT) { | ||
| 553 | + CHECK(connected_); | ||
| 554 | + connected_ = false; | ||
| 555 | + if (!shutting_down_) | ||
| 556 | + PrintDebuggerReadyMessage(port_); | ||
| 557 | + inspector_->quitMessageLoopOnPause(); | ||
| 558 | + inspector_->disconnectFrontend(); | ||
| 559 | + } else { | ||
| 560 | + inspector_->dispatchMessageFromFrontend(message); | ||
| 561 | + } | ||
| 562 | + } | ||
| 541 | 563 | uv_async_send(&data_written_); | |
| 542 | 564 | dispatching_messages_ = false; | |
| 543 | 565 | } | |
| 544 | 566 | ||
| 545 | - void AgentImpl::SetConnected(bool connected) { | ||
| 546 | - if (connected_ == connected) | ||
| 547 | - return; | ||
| 548 | - | ||
| 549 | - connected_ = connected; | ||
| 550 | - if (connected) { | ||
| 551 | - fprintf(stderr, "Debugger attached.\n"); | ||
| 552 | - inspector_->connectFrontend(new ChannelImpl(this)); | ||
| 553 | - } else { | ||
| 554 | - if (!shutting_down_) | ||
| 555 | - PrintDebuggerReadyMessage(port_); | ||
| 556 | - inspector_->quitMessageLoopOnPause(); | ||
| 557 | - inspector_->disconnectFrontend(); | ||
| 558 | - } | ||
| 559 | - } | ||
| 560 | - | ||
| 561 | - void AgentImpl::Write(const std::string& message) { | ||
| 562 | - PushPendingMessage(&outgoing_message_queue_, message); | ||
| 563 | - ASSERT_EQ(0, uv_async_send(&io_thread_req_)); | ||
| 567 | + void AgentImpl::Write(int session_id, const String16& message) { | ||
| 568 | + AppendMessage(&outgoing_message_queue_, session_id, message); | ||
| 569 | + int err = uv_async_send(&io_thread_req_); | ||
| 570 | + CHECK_EQ(0, err); | ||
| 564 | 571 | } | |
| 565 | 572 | ||
| 566 | 573 | // Exported class Agent | |
| Back | FazBrowse Home | New Git URL |
0 commit comments