Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(480)

Unified Diff: runtime/bin/dbg_connection.cc

Issue 1497033003: - Remove the legacy debug protocol. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: runtime/bin/dbg_connection.cc
diff --git a/runtime/bin/dbg_connection.cc b/runtime/bin/dbg_connection.cc
deleted file mode 100644
index 6bd0cda256d67e5e109ffefcf55b1910c1461fc4..0000000000000000000000000000000000000000
--- a/runtime/bin/dbg_connection.cc
+++ /dev/null
@@ -1,526 +0,0 @@
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-#include "bin/dbg_connection.h"
-#include "bin/dbg_message.h"
-#include "bin/dartutils.h"
-#include "bin/lockers.h"
-#include "bin/log.h"
-#include "bin/socket.h"
-#include "bin/thread.h"
-#include "bin/utils.h"
-
-#include "platform/globals.h"
-#include "platform/json.h"
-#include "platform/utils.h"
-
-#include "include/dart_api.h"
-
-
-namespace dart {
-namespace bin {
-
-bool trace_debug_protocol = false;
-
-intptr_t DebuggerConnectionHandler::listener_fd_ = -1;
-Monitor* DebuggerConnectionHandler::handler_lock_ = new Monitor();
-
-// TODO(asiva): Remove this once we have support for multiple debugger
-// connections. For now we just store the single debugger connection
-// handler in a static variable.
-static DebuggerConnectionHandler* singleton_handler = NULL;
-
-// The maximum message length to print when --trace_debug_protocol is
-// specified.
-static const int kMaxPrintMessageLen = 1024;
-
-class MessageBuffer {
- public:
- explicit MessageBuffer(intptr_t fd);
- ~MessageBuffer();
- void ReadData();
- bool IsValidMessage() const;
- void PopMessage();
- int MessageId() const;
- char* buf() const { return buf_; }
- bool Alive() const { return connection_is_alive_; }
-
- private:
- static const int kInitialBufferSize = 256;
- char* buf_;
- int buf_length_;
- intptr_t fd_;
- int data_length_;
- bool connection_is_alive_;
-
- DISALLOW_COPY_AND_ASSIGN(MessageBuffer);
-};
-
-
-MessageBuffer::MessageBuffer(intptr_t fd)
- : buf_(NULL),
- buf_length_(0),
- fd_(fd),
- data_length_(0),
- connection_is_alive_(true) {
- buf_ = reinterpret_cast<char*>(malloc(kInitialBufferSize));
- if (buf_ == NULL) {
- FATAL("Failed to allocate message buffer\n");
- }
- buf_length_ = kInitialBufferSize;
- buf_[0] = '\0';
- data_length_ = 0;
-}
-
-
-MessageBuffer::~MessageBuffer() {
- free(buf_);
- buf_ = NULL;
- fd_ = -1;
-}
-
-
-bool MessageBuffer::IsValidMessage() const {
- if (data_length_ == 0) {
- return false;
- }
- dart::JSONReader msg_reader(buf_);
- return msg_reader.EndOfObject() != NULL;
-}
-
-
-int MessageBuffer::MessageId() const {
- dart::JSONReader r(buf_);
- r.Seek("id");
- if (r.Type() == dart::JSONReader::kInteger) {
- return atoi(r.ValueChars());
- } else {
- return -1;
- }
-}
-
-
-void MessageBuffer::ReadData() {
- ASSERT(data_length_ >= 0);
- ASSERT(data_length_ < buf_length_);
- int max_read = buf_length_ - data_length_ - 1;
- if (max_read == 0) {
- // TODO(hausner):
- // Buffer is full. What should we do if there is no valid message
- // in the buffer? This might be possible if the client sends a message
- // that's larger than the buffer, of if the client sends malformed
- // messages that keep piling up.
- ASSERT(IsValidMessage());
- return;
- }
- // TODO(hausner): Handle error conditions returned by Read. We may
- // want to close the debugger connection if we get any errors.
- int bytes_read =
- DebuggerConnectionImpl::Receive(fd_, buf_ + data_length_, max_read);
- if (bytes_read == 0) {
- connection_is_alive_ = false;
- return;
- }
- ASSERT(bytes_read > 0);
- data_length_ += bytes_read;
- ASSERT(data_length_ < buf_length_);
- buf_[data_length_] = '\0';
-}
-
-
-void MessageBuffer::PopMessage() {
- dart::JSONReader msg_reader(buf_);
- const char* end = msg_reader.EndOfObject();
- if (end != NULL) {
- ASSERT(*end == '}');
- end++;
- data_length_ = 0;
- while (*end != '\0') {
- buf_[data_length_] = *end++;
- data_length_++;
- }
- buf_[data_length_] = '\0';
- ASSERT(data_length_ < buf_length_);
- }
-}
-
-
-static bool IsValidJSON(const char* msg) {
- dart::JSONReader r(msg);
- return r.CheckMessage();
-}
-
-
-DebuggerConnectionHandler::DebuggerConnectionHandler(intptr_t debug_fd)
- : debug_fd_(debug_fd), msgbuf_(NULL) {
- msgbuf_ = new MessageBuffer(debug_fd_);
-}
-
-
-DebuggerConnectionHandler::~DebuggerConnectionHandler() {
- CloseDbgConnection();
- DebuggerConnectionHandler::RemoveDebuggerConnection(debug_fd_);
-}
-
-
-int DebuggerConnectionHandler::MessageId() {
- ASSERT(msgbuf_ != NULL);
- return msgbuf_->MessageId();
-}
-
-
-void DebuggerConnectionHandler::HandleUnknownMsg() {
- int msg_id = msgbuf_->MessageId();
- ASSERT(msg_id >= 0);
- SendError(debug_fd_, msg_id, "unknown debugger command");
-}
-
-
-typedef void (*CommandHandler)(DbgMessage* msg);
-
-struct JSONDebuggerCommand {
- const char* cmd_string;
- CommandHandler handler_function;
-};
-
-
-void DebuggerConnectionHandler::HandleMessages() {
- static JSONDebuggerCommand generic_debugger_commands[] = {
- { "interrupt", HandleInterruptCmd },
- { "getIsolateIds", HandleIsolatesListCmd },
- { NULL, NULL }
- };
-
- for (;;) {
- // Read a message.
- while (!msgbuf_->IsValidMessage() && msgbuf_->Alive()) {
- msgbuf_->ReadData();
- }
- if (!msgbuf_->Alive()) {
- if (trace_debug_protocol) {
- Log::Print("Debugger is exiting HandleMessages loop.\n");
- }
- return;
- }
-
- if (trace_debug_protocol) {
- dart::JSONReader r(msgbuf_->buf());
- const char* msg_end = r.EndOfObject();
- if (msg_end != NULL) {
- intptr_t msg_len = msg_end - msgbuf_->buf();
- int print_len = ((msg_len > kMaxPrintMessageLen)
- ? kMaxPrintMessageLen : msg_len);
- Log::Print("[<<<] Receiving message from debug fd %" Pd ":\n%.*s%s\n",
- debug_fd_, print_len, msgbuf_->buf(),
- ((msg_len > print_len) ? "..." : ""));
- }
- }
-
- // Parse out the command portion from the message.
- dart::JSONReader r(msgbuf_->buf());
- bool found = r.Seek("command");
- if (r.Error()) {
- FATAL("Illegal JSON message received");
- }
- if (!found) {
- Log::Print("'command' not found in JSON message: '%s'\n",
- msgbuf_->buf());
- msgbuf_->PopMessage();
- }
-
- // Check if this is a generic command (not isolate specific).
- int i = 0;
- bool is_handled = false;
- while (generic_debugger_commands[i].cmd_string != NULL) {
- if (r.IsStringLiteral(generic_debugger_commands[i].cmd_string)) {
- DbgMessage* msg = new DbgMessage(i,
- msgbuf_->buf(),
- r.EndOfObject(),
- debug_fd_);
- (*generic_debugger_commands[i].handler_function)(msg);
- is_handled = true;
- msgbuf_->PopMessage();
- delete msg;
- break;
- }
- i++;
- }
- if (!is_handled) {
- // Check if this is an isolate specific command.
- int32_t cmd_idx = DbgMsgQueueList::LookupIsolateCommand(r.ValueChars(),
- r.ValueLen());
- if (cmd_idx != DbgMsgQueueList::kInvalidCommand) {
- const char* start = msgbuf_->buf();
- const char* end = r.EndOfObject();
- // Get debug message queue corresponding to isolate.
- MessageParser msg_parser(start, (end - start));
- Dart_IsolateId isolate_id = msg_parser.GetInt64Param("isolateId");
- if (!DbgMsgQueueList::AddIsolateMessage(isolate_id,
- cmd_idx,
- msgbuf_->buf(),
- r.EndOfObject(),
- debug_fd_)) {
- SendError(debug_fd_, MessageId(), "Invalid isolate specified");
- }
- msgbuf_->PopMessage();
- continue;
- }
-
- // This is an unrecognized command, report error and move on to next.
- Log::Print("unrecognized command received: '%s'\n", msgbuf_->buf());
- HandleUnknownMsg();
- msgbuf_->PopMessage();
- }
- }
-}
-
-
-void DebuggerConnectionHandler::SendError(intptr_t debug_fd,
- int msg_id,
- const char* err_msg) {
- dart::TextBuffer msg(64);
- msg.Printf("{\"id\": %d, \"error\": \"Error: ", msg_id);
- msg.AddEscapedString(err_msg);
- msg.Printf("\"}");
- SendMsg(debug_fd, &msg);
-}
-
-
-void DebuggerConnectionHandler::CloseDbgConnection() {
- if (debug_fd_ >= 0) {
- Socket::Close(debug_fd_);
- }
- if (msgbuf_ != NULL) {
- delete msgbuf_;
- msgbuf_ = NULL;
- }
- // TODO(hausner): Need to tell the VM debugger object to remove all
- // breakpoints.
-}
-
-
-// The vm service relies on certain debugger functionality.
-void DebuggerConnectionHandler::InitForVmService() {
- MonitorLocker ml(handler_lock_);
- DbgMsgQueueList::Initialize();
-}
-
-
-int DebuggerConnectionHandler::StartHandler(const char* address,
- int port_number) {
- ASSERT(handler_lock_ != NULL);
- MonitorLocker ml(handler_lock_);
- if (IsListening()) {
- // The debugger connection handler was already started.
- return Socket::GetPort(listener_fd_);
- }
-
- // First setup breakpoint, exception and delayed breakpoint handlers.
- DbgMsgQueueList::Initialize();
-
- // Initialize the socket implementation.
- if (!Socket::Initialize()) {
- FATAL("Failed initializing socket implementation.");
- }
-
- // Now setup a listener socket and start a thread which will
- // listen, accept connections from debuggers, read and handle/dispatch
- // debugger commands received on these connections.
- ASSERT(listener_fd_ == -1);
- OSError *os_error;
- AddressList<SocketAddress>* addresses =
- Socket::LookupAddress(address, -1, &os_error);
- RawAddr addr = addresses->GetAt(0)->addr();
- SocketAddress::SetAddrPort(&addr, port_number);
- listener_fd_ = ServerSocket::CreateBindListen(addr, 1);
- delete addresses;
- if (listener_fd_ < 0) {
- fprintf(stderr, "%s", "Could not initialize debug socket\n");
- fflush(stderr);
- exit(255);
- }
-
- port_number = Socket::GetPort(listener_fd_);
- DebuggerConnectionImpl::StartHandler(port_number);
- return port_number;
-}
-
-
-void DebuggerConnectionHandler::StopHandler() {
- if (IsConnected()) {
- DebuggerConnectionImpl::StopHandler(singleton_handler->debug_fd());
- }
-}
-
-
-void DebuggerConnectionHandler::WaitForConnection() {
- ASSERT(handler_lock_ != NULL);
- MonitorLocker ml(handler_lock_);
- if (!IsListening()) {
- // If we are only running the vm service, don't wait for
- // connections.
- return;
- }
- while (!IsConnected()) {
- Monitor::WaitResult res = ml.Wait();
- ASSERT(res == Monitor::kNotified);
- }
-}
-
-
-void DebuggerConnectionHandler::SendMsg(intptr_t debug_fd,
- dart::TextBuffer* msg) {
- ASSERT(handler_lock_ != NULL);
- MonitorLocker ml(handler_lock_);
- SendMsgHelper(debug_fd, msg);
-}
-
-
-void DebuggerConnectionHandler::BroadcastMsg(dart::TextBuffer* msg) {
- ASSERT(handler_lock_ != NULL);
- MonitorLocker ml(handler_lock_);
- if (!IsListening()) {
- // If we are only running the vm service, don't try to broadcast
- // to debugger clients.
- return;
- }
- // TODO(asiva): Once we support connection to multiple debuggers
- // we need to send the message to all of them.
- ASSERT(singleton_handler != NULL);
- SendMsgHelper(singleton_handler->debug_fd(), msg);
-}
-
-
-void DebuggerConnectionHandler::SendMsgHelper(intptr_t debug_fd,
- dart::TextBuffer* msg) {
- ASSERT(debug_fd >= 0);
- ASSERT(IsValidJSON(msg->buf()));
-
- if (trace_debug_protocol) {
- int print_len = ((msg->length() > kMaxPrintMessageLen)
- ? kMaxPrintMessageLen : msg->length());
- Log::Print("[>>>] Sending message to debug fd %" Pd ":\n%.*s%s\n",
- debug_fd, print_len, msg->buf(),
- ((msg->length() > print_len) ? "..." : ""));
- }
-
- // Sending messages in short pieces can be used to stress test the
- // debugger front-end's message handling code.
- const bool send_in_pieces = false;
- if (send_in_pieces) {
- intptr_t remaining = msg->length();
- intptr_t sent = 0;
- const intptr_t max_piece_len = 122; // Pretty arbitrary, not a power of 2.
- Monitor sleep;
- while (remaining > 0) {
- intptr_t piece_len = remaining;
- if (piece_len > max_piece_len) {
- piece_len = max_piece_len;
- }
- intptr_t written =
- DebuggerConnectionImpl::Send(debug_fd, msg->buf() + sent, piece_len);
- ASSERT(written == piece_len);
- sent += written;
- remaining -= written;
- // Wait briefly so the OS does not coalesce message fragments.
- {
- MonitorLocker ml(&sleep);
- ml.Wait(10);
- }
- }
- return;
- }
- intptr_t bytes_written =
- DebuggerConnectionImpl::Send(debug_fd, msg->buf(), msg->length());
- ASSERT(msg->length() == bytes_written);
- // TODO(hausner): Error checking. Probably just shut down the debugger
- // session if we there is an error while writing.
-}
-
-
-void DebuggerConnectionHandler::AcceptDbgConnection(intptr_t debug_fd) {
- Socket::SetNoDelay(debug_fd, true);
- AddNewDebuggerConnection(debug_fd);
- {
- ASSERT(handler_lock_ != NULL);
- MonitorLocker ml(handler_lock_);
- ml.NotifyAll();
- }
- // TODO(asiva): Once we implement support for multiple connections
- // we should have a different callback for wakeups on fds which
- // are not the listener_fd_.
- // In that callback we would lookup the handler object
- // corresponding to that fd and invoke HandleMessages on it.
- // For now we run that code here.
- DebuggerConnectionHandler* handler = GetDebuggerConnectionHandler(debug_fd);
- if (handler != NULL) {
- handler->HandleMessages();
- delete handler;
- }
-}
-
-
-void DebuggerConnectionHandler::HandleInterruptCmd(DbgMessage* in_msg) {
- MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
- int msg_id = msg_parser.MessageId();
- Dart_IsolateId isolate_id = msg_parser.GetInt64Param("isolateId");
- if (isolate_id == ILLEGAL_ISOLATE_ID || Dart_GetIsolate(isolate_id) == NULL) {
- in_msg->SendErrorReply(msg_id, "Invalid isolate specified");
- return;
- }
- if (!DbgMsgQueueList::InterruptIsolate(isolate_id)) {
- in_msg->SendErrorReply(msg_id, "Invalid isolate specified");
- return;
- }
- dart::TextBuffer msg(64);
- msg.Printf("{ \"id\": %d }", msg_id);
- in_msg->SendReply(&msg);
-}
-
-
-void DebuggerConnectionHandler::HandleIsolatesListCmd(DbgMessage* in_msg) {
- MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
- int msg_id = msg_parser.MessageId();
- ASSERT(msg_id >= 0);
- dart::TextBuffer msg(64);
- msg.Printf("{ \"id\": %d, \"result\": { \"isolateIds\": [", msg_id);
- DbgMsgQueueList::ListIsolateIds(&msg);
- msg.Printf("]}}");
- in_msg->SendReply(&msg);
-}
-
-
-void DebuggerConnectionHandler::AddNewDebuggerConnection(intptr_t debug_fd) {
- // TODO(asiva): Support multiple debugger connections, for now we just
- // create one handler, store it in a static variable and use it.
- ASSERT(singleton_handler == NULL);
- singleton_handler = new DebuggerConnectionHandler(debug_fd);
-}
-
-
-void DebuggerConnectionHandler::RemoveDebuggerConnection(intptr_t debug_fd) {
- // TODO(asiva): Support multiple debugger connections, for now we just
- // set the static handler back to NULL.
- ASSERT(singleton_handler != NULL);
- singleton_handler = NULL;
-}
-
-
-DebuggerConnectionHandler*
-DebuggerConnectionHandler::GetDebuggerConnectionHandler(intptr_t debug_fd) {
- // TODO(asiva): Support multiple debugger connections, for now we just
- // return the one static handler that was created.
- ASSERT(singleton_handler != NULL);
- return singleton_handler;
-}
-
-
-bool DebuggerConnectionHandler::IsConnected() {
- // TODO(asiva): Support multiple debugger connections.
- // Return true if a connection has been established.
- return singleton_handler != NULL;
-}
-
-} // namespace bin
-} // namespace dart

Powered by Google App Engine
This is Rietveld 408576698