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

Unified Diff: runtime/bin/dbg_connection.cc

Issue 10990089: First step towards support for being able to interrupt a running Dart Isolate (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 2 months 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
« no previous file with comments | « runtime/bin/dbg_connection.h ('k') | runtime/bin/dbg_connection_linux.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/bin/dbg_connection.cc
===================================================================
--- runtime/bin/dbg_connection.cc (revision 13147)
+++ runtime/bin/dbg_connection.cc (working copy)
@@ -3,6 +3,7 @@
// 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/socket.h"
#include "bin/thread.h"
@@ -17,34 +18,14 @@
int DebuggerConnectionHandler::listener_fd_ = -1;
-int DebuggerConnectionHandler::debugger_fd_ = -1;
-dart::Monitor DebuggerConnectionHandler::is_connected_;
-MessageBuffer* DebuggerConnectionHandler::msgbuf_ = NULL;
+dart::Monitor DebuggerConnectionHandler::handler_lock_;
-bool DebuggerConnectionHandler::handler_started_ = false;
-bool DebuggerConnectionHandler::request_resume_ = false;
+// 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;
-dart::TextBuffer DebuggerConnectionHandler::queued_messages_(64);
-
-// TODO(hausner): Need better error handling.
-#define ASSERT_NOT_ERROR(handle) \
- ASSERT(!Dart_IsError(handle))
-
-#define RETURN_IF_ERROR(handle) \
- if (Dart_IsError(handle)) { \
- return Dart_GetError(handle); \
- }
-
-
-typedef void (*CommandHandler)(const char* json_cmd);
-
-struct JSONDebuggerCommand {
- const char* cmd_string;
- CommandHandler handler_function;
-};
-
-
class MessageBuffer {
public:
explicit MessageBuffer(int fd);
@@ -53,11 +34,6 @@
bool IsValidMessage() const;
void PopMessage();
int MessageId() const;
- const char* Params() const;
- intptr_t GetIntParam(const char* name) const;
- intptr_t GetOptIntParam(const char* name, intptr_t default_val) const;
- // GetStringParam mallocs the buffer that it returns. Caller must free.
- char* GetStringParam(const char* name) const;
char* buf() const { return buf_; }
bool Alive() const { return connection_is_alive_; }
@@ -75,10 +51,10 @@
MessageBuffer::MessageBuffer(int fd)
: buf_(NULL),
- buf_length_(0),
- fd_(fd),
- data_length_(0),
- connection_is_alive_(true) {
+ 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");
@@ -116,56 +92,6 @@
}
-const char* MessageBuffer::Params() const {
- dart::JSONReader r(buf_);
- r.Seek("params");
- if (r.Type() == dart::JSONReader::kObject) {
- return r.ValueChars();
- } else {
- return NULL;
- }
-}
-
-
-intptr_t MessageBuffer::GetIntParam(const char* name) const {
- const char* params = Params();
- ASSERT(params != NULL);
- dart::JSONReader r(params);
- r.Seek(name);
- ASSERT(r.Type() == dart::JSONReader::kInteger);
- return strtol(r.ValueChars(), NULL, 10);
-}
-
-
-intptr_t MessageBuffer::GetOptIntParam(const char* name,
- intptr_t default_val) const {
- const char* params = Params();
- ASSERT(params != NULL);
- dart::JSONReader r(params);
- r.Seek(name);
- if (r.Type() == dart::JSONReader::kInteger) {
- return strtol(r.ValueChars(), NULL, 10);
- } else {
- return default_val;
- }
-}
-
-
-char* MessageBuffer::GetStringParam(const char* name) const {
- const char* params = Params();
- ASSERT(params != NULL);
- dart::JSONReader pr(params);
- pr.Seek(name);
- if (pr.Type() != dart::JSONReader::kString) {
- return NULL;
- }
- intptr_t buflen = pr.ValueLen() + 1;
- char* param_chars = reinterpret_cast<char*>(malloc(buflen));
- pr.GetValueChars(param_chars, buflen);
- // TODO(hausner): Decode escape sequences.
- return param_chars;
-}
-
void MessageBuffer::ReadData() {
ASSERT(data_length_ >= 0);
ASSERT(data_length_ < buf_length_);
@@ -216,722 +142,57 @@
}
-void DebuggerConnectionHandler::SendMsg(dart::TextBuffer* msg) {
- ASSERT(debugger_fd_ >= 0);
- ASSERT(IsValidJSON(msg->buf()));
- // 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.
- dart::Monitor sleep;
- while (remaining > 0) {
- intptr_t piece_len = remaining;
- if (piece_len > max_piece_len) {
- piece_len = max_piece_len;
- }
- intptr_t written =
- Socket::Write(debugger_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 =
- Socket::Write(debugger_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.
+DebuggerConnectionHandler::DebuggerConnectionHandler(int debug_fd)
+ : debug_fd_(debug_fd), msgbuf_(NULL) {
+ msgbuf_ = new MessageBuffer(debug_fd_);
}
-void DebuggerConnectionHandler::QueueMsg(dart::TextBuffer* msg) {
- queued_messages_.Printf("%s", msg->buf());
+DebuggerConnectionHandler::~DebuggerConnectionHandler() {
+ CloseDbgConnection();
+ DebuggerConnectionHandler::RemoveDebuggerConnection(debug_fd_);
}
-void DebuggerConnectionHandler::SendQueuedMsgs() {
- if (queued_messages_.length() > 0) {
- SendMsg(&queued_messages_);
- queued_messages_.Clear();
- }
+int DebuggerConnectionHandler::MessageId() {
+ ASSERT(msgbuf_ != NULL);
+ return msgbuf_->MessageId();
}
-void DebuggerConnectionHandler::SendError(int msg_id,
- const char* err_msg) {
- dart::TextBuffer msg(64);
- msg.Printf("{\"id\": %d, \"error\": \"Error: %s\"}", msg_id, err_msg);
- SendMsg(&msg);
-}
-
-
-static const char* GetStringChars(Dart_Handle str) {
- ASSERT(Dart_IsString(str));
- const char* chars;
- Dart_Handle res = Dart_StringToCString(str, &chars);
- ASSERT(!Dart_IsError(res));
- return chars;
-}
-
-
-static int GetIntValue(Dart_Handle int_handle) {
- int64_t int64_val = -1;
- ASSERT(Dart_IsInteger(int_handle));
- Dart_Handle res = Dart_IntegerToInt64(int_handle, &int64_val);
- ASSERT_NOT_ERROR(res);
- // TODO(hausner): Range check.
- return int64_val;
-}
-
-
-void DebuggerConnectionHandler::HandleResumeCmd(const char* json_msg) {
+void DebuggerConnectionHandler::HandleUnknownMsg() {
int msg_id = msgbuf_->MessageId();
- dart::TextBuffer msg(64);
- msg.Printf("{ \"id\": %d }", msg_id);
- SendMsg(&msg);
- request_resume_ = true;
+ ASSERT(msg_id >= 0);
+ SendError(debug_fd_, msg_id, "unknown debugger command");
}
-void DebuggerConnectionHandler::HandleStepIntoCmd(const char* json_msg) {
- Dart_Handle res = Dart_SetStepInto();
- ASSERT_NOT_ERROR(res);
- HandleResumeCmd(json_msg);
-}
+typedef void (*CommandHandler)(DebuggerConnectionHandler* handler);
+struct JSONDebuggerCommand {
+ const char* cmd_string;
+ CommandHandler handler_function;
+};
-void DebuggerConnectionHandler::HandleStepOutCmd(const char* json_msg) {
- Dart_Handle res = Dart_SetStepOut();
- ASSERT_NOT_ERROR(res);
- HandleResumeCmd(json_msg);
-}
-
-void DebuggerConnectionHandler::HandleStepOverCmd(const char* json_msg) {
- Dart_Handle res = Dart_SetStepOver();
- ASSERT_NOT_ERROR(res);
- HandleResumeCmd(json_msg);
-}
-
-
-static void FormatEncodedString(dart::TextBuffer* buf, Dart_Handle str) {
- intptr_t str_len = 0;
- Dart_Handle res = Dart_StringLength(str, &str_len);
- ASSERT_NOT_ERROR(res);
- uint32_t* codepoints =
- reinterpret_cast<uint32_t*>(malloc(str_len * sizeof(uint32_t)));
- ASSERT(codepoints != NULL);
- intptr_t actual_len = str_len;
- res = Dart_StringGet32(str, codepoints, &actual_len);
- ASSERT_NOT_ERROR(res);
- ASSERT(str_len == actual_len);
- buf->AddChar('\"');
- for (int i = 0; i < str_len; i++) {
- buf->AddEscapedChar(codepoints[i]);
- }
- buf->AddChar('\"');
- free(codepoints);
-}
-
-
-static void FormatErrorMsg(dart::TextBuffer* buf, Dart_Handle err) {
- // TODO(hausner): Turn message into Dart string and
- // properly encode the message.
- ASSERT(Dart_IsError(err));
- const char* msg = Dart_GetError(err);
- buf->Printf("\"%s\"", msg);
-}
-
-
-void DebuggerConnectionHandler::HandleGetScriptURLsCmd(const char* json_msg) {
- int msg_id = msgbuf_->MessageId();
- dart::TextBuffer msg(64);
- intptr_t lib_id = msgbuf_->GetIntParam("libraryId");
- Dart_Handle lib_url = Dart_GetLibraryURL(lib_id);
- ASSERT_NOT_ERROR(lib_url);
- Dart_Handle urls = Dart_GetScriptURLs(lib_url);
- if (Dart_IsError(urls)) {
- SendError(msg_id, Dart_GetError(urls));
- return;
- }
- ASSERT(Dart_IsList(urls));
- intptr_t num_urls = 0;
- Dart_ListLength(urls, &num_urls);
- msg.Printf("{ \"id\": %d, ", msg_id);
- msg.Printf("\"result\": { \"urls\": [");
- for (int i = 0; i < num_urls; i++) {
- Dart_Handle script_url = Dart_ListGetAt(urls, i);
- if (i > 0) {
- msg.Printf(",");
- }
- FormatEncodedString(&msg, script_url);
- }
- msg.Printf("]}}");
- SendMsg(&msg);
-}
-
-
-void DebuggerConnectionHandler::HandleGetSourceCmd(const char* json_msg) {
- int msg_id = msgbuf_->MessageId();
- dart::TextBuffer msg(64);
- intptr_t lib_id = msgbuf_->GetIntParam("libraryId");
- char* url_chars = msgbuf_->GetStringParam("url");
- ASSERT(url_chars != NULL);
- Dart_Handle url = Dart_NewString(url_chars);
- ASSERT_NOT_ERROR(url);
- free(url_chars);
- url_chars = NULL;
- Dart_Handle source = Dart_ScriptGetSource(lib_id, url);
- if (Dart_IsError(source)) {
- SendError(msg_id, Dart_GetError(source));
- return;
- }
- msg.Printf("{ \"id\": %d, ", msg_id);
- msg.Printf("\"result\": { \"text\": ");
- FormatEncodedString(&msg, source);
- msg.Printf("}}");
- SendMsg(&msg);
-}
-
-
-void DebuggerConnectionHandler::HandleGetLibrariesCmd(const char* json_msg) {
- int msg_id = msgbuf_->MessageId();
- dart::TextBuffer msg(64);
- msg.Printf("{ \"id\": %d, \"result\": { \"libraries\": [", msg_id);
- Dart_Handle lib_ids = Dart_GetLibraryIds();
- ASSERT_NOT_ERROR(lib_ids);
- intptr_t num_libs;
- Dart_Handle res = Dart_ListLength(lib_ids, &num_libs);
- ASSERT_NOT_ERROR(res);
- for (int i = 0; i < num_libs; i++) {
- Dart_Handle lib_id_handle = Dart_ListGetAt(lib_ids, i);
- ASSERT(Dart_IsInteger(lib_id_handle));
- int lib_id = GetIntValue(lib_id_handle);
- Dart_Handle lib_url = Dart_GetLibraryURL(lib_id);
- ASSERT_NOT_ERROR(lib_url);
- ASSERT(Dart_IsString(lib_url));
- msg.Printf("%s{\"id\":%d,\"url\":", (i == 0) ? "" : ", ", lib_id);
- FormatEncodedString(&msg, lib_url);
- msg.Printf("}");
- }
- msg.Printf("]}}");
- SendMsg(&msg);
-}
-
-
-static void FormatTextualValue(dart::TextBuffer* buf, Dart_Handle object) {
- Dart_Handle text;
- if (Dart_IsNull(object)) {
- text = Dart_Null();
- } else {
- Dart_ExceptionPauseInfo savedState = Dart_GetExceptionPauseInfo();
-
- // TODO(hausner): Check whether recursive/reentrant pauses on exceptions
- // should be prevented in Debugger::SignalExceptionThrown() instead.
- if (savedState != kNoPauseOnExceptions) {
- Dart_Handle res = Dart_SetExceptionPauseInfo(kNoPauseOnExceptions);
- ASSERT_NOT_ERROR(res);
- }
-
- text = Dart_ToString(object);
-
- if (savedState != kNoPauseOnExceptions) {
- Dart_Handle res = Dart_SetExceptionPauseInfo(savedState);
- ASSERT_NOT_ERROR(res);
- }
- }
- buf->Printf("\"text\":");
- if (Dart_IsNull(text)) {
- buf->Printf("null");
- } else if (Dart_IsError(text)) {
- FormatErrorMsg(buf, text);
- } else {
- FormatEncodedString(buf, text);
- }
-}
-
-
-static void FormatValue(dart::TextBuffer* buf, Dart_Handle object) {
- if (Dart_IsInteger(object)) {
- buf->Printf("\"kind\":\"integer\",");
- } else if (Dart_IsString(object)) {
- buf->Printf("\"kind\":\"string\",");
- } else if (Dart_IsBoolean(object)) {
- buf->Printf("\"kind\":\"boolean\",");
- } else if (Dart_IsList(object)) {
- intptr_t len = 0;
- Dart_Handle res = Dart_ListLength(object, &len);
- ASSERT_NOT_ERROR(res);
- buf->Printf("\"kind\":\"list\",\"length\":%"Pd",", len);
- } else {
- buf->Printf("\"kind\":\"object\",");
- }
- FormatTextualValue(buf, object);
-}
-
-
-static void FormatValueObj(dart::TextBuffer* buf, Dart_Handle object) {
- buf->Printf("{");
- FormatValue(buf, object);
- buf->Printf("}");
-}
-
-
-static void FormatRemoteObj(dart::TextBuffer* buf, Dart_Handle object) {
- intptr_t obj_id = Dart_CacheObject(object);
- ASSERT(obj_id >= 0);
- buf->Printf("{\"objectId\":%"Pd",", obj_id);
- FormatValue(buf, object);
- buf->Printf("}");
-}
-
-
-static void FormatNamedValue(dart::TextBuffer* buf,
- Dart_Handle object_name,
- Dart_Handle object) {
- ASSERT(Dart_IsString(object_name));
- buf->Printf("{\"name\":\"%s\",", GetStringChars(object_name));
- buf->Printf("\"value\":");
- FormatRemoteObj(buf, object);
- buf->Printf("}");
-}
-
-
-static void FormatNamedValueList(dart::TextBuffer* buf,
- Dart_Handle obj_list) {
- ASSERT(Dart_IsList(obj_list));
- intptr_t list_length = 0;
- Dart_Handle res = Dart_ListLength(obj_list, &list_length);
- ASSERT_NOT_ERROR(res);
- ASSERT(list_length % 2 == 0);
- buf->Printf("[");
- for (int i = 0; i + 1 < list_length; i += 2) {
- Dart_Handle name_handle = Dart_ListGetAt(obj_list, i);
- ASSERT_NOT_ERROR(name_handle);
- Dart_Handle value_handle = Dart_ListGetAt(obj_list, i + 1);
- ASSERT_NOT_ERROR(value_handle);
- if (i > 0) {
- buf->Printf(",");
- }
- FormatNamedValue(buf, name_handle, value_handle);
- }
- buf->Printf("]");
-}
-
-
-static const char* FormatClassProps(dart::TextBuffer* buf,
- intptr_t cls_id) {
- Dart_Handle name, static_fields;
- intptr_t super_id = -1;
- intptr_t library_id = -1;
- Dart_Handle res =
- Dart_GetClassInfo(cls_id, &name, &library_id, &super_id, &static_fields);
- RETURN_IF_ERROR(res);
- RETURN_IF_ERROR(name);
- buf->Printf("{\"name\":\"%s\",", GetStringChars(name));
- if (super_id > 0) {
- buf->Printf("\"superclassId\":%"Pd",", super_id);
- }
- buf->Printf("\"libraryId\":%"Pd",", library_id);
- RETURN_IF_ERROR(static_fields);
- buf->Printf("\"fields\":");
- FormatNamedValueList(buf, static_fields);
- buf->Printf("}");
- return NULL;
-}
-
-
-static const char* FormatLibraryProps(dart::TextBuffer* buf,
- intptr_t lib_id) {
- Dart_Handle url = Dart_GetLibraryURL(lib_id);
- RETURN_IF_ERROR(url);
- buf->Printf("{\"url\":");
- FormatEncodedString(buf, url);
-
- // Whether debugging is enabled.
- bool is_debuggable = false;
- Dart_Handle res = Dart_GetLibraryDebuggable(lib_id, &is_debuggable);
- RETURN_IF_ERROR(res);
- buf->Printf(",\"debuggingEnabled\":%s",
- is_debuggable ? "\"true\"" : "\"false\"");
-
- // Imports and prefixes.
- Dart_Handle import_list = Dart_GetLibraryImports(lib_id);
- RETURN_IF_ERROR(import_list);
- ASSERT(Dart_IsList(import_list));
- intptr_t list_length = 0;
- res = Dart_ListLength(import_list, &list_length);
- RETURN_IF_ERROR(res);
- buf->Printf(",\"imports\":[");
- for (int i = 0; i + 1 < list_length; i += 2) {
- Dart_Handle lib_id = Dart_ListGetAt(import_list, i + 1);
- ASSERT_NOT_ERROR(lib_id);
- buf->Printf("%s{\"libraryId\":%d,",
- (i > 0) ? ",": "",
- GetIntValue(lib_id));
-
- Dart_Handle name = Dart_ListGetAt(import_list, i);
- ASSERT_NOT_ERROR(name);
- buf->Printf("\"prefix\":\"%s\"}",
- Dart_IsNull(name) ? "" : GetStringChars(name));
- }
- buf->Printf("],");
-
- // Global variables in the library.
- Dart_Handle global_vars = Dart_GetLibraryFields(lib_id);
- RETURN_IF_ERROR(global_vars);
- buf->Printf("\"globals\":");
- FormatNamedValueList(buf, global_vars);
- buf->Printf("}");
- return NULL;
-}
-
-
-static const char* FormatObjProps(dart::TextBuffer* buf,
- Dart_Handle object) {
- intptr_t class_id;
- if (Dart_IsNull(object)) {
- buf->Printf("{\"classId\":-1,\"fields\":[]}");
- return NULL;
- }
- Dart_Handle res = Dart_GetObjClassId(object, &class_id);
- RETURN_IF_ERROR(res);
- buf->Printf("{\"classId\": %"Pd",", class_id);
- buf->Printf("\"kind\":\"object\",\"fields\":");
- Dart_Handle fields = Dart_GetInstanceFields(object);
- RETURN_IF_ERROR(fields);
- FormatNamedValueList(buf, fields);
- buf->Printf("}");
- return NULL;
-}
-
-
-static const char* FormatListSlice(dart::TextBuffer* buf,
- Dart_Handle list,
- intptr_t list_length,
- intptr_t index,
- intptr_t slice_length) {
- intptr_t end_index = index + slice_length;
- ASSERT(end_index <= list_length);
- buf->Printf("{\"index\":%"Pd",", index);
- buf->Printf("\"length\":%"Pd",", slice_length);
- buf->Printf("\"elements\":[");
- for (intptr_t i = index; i < end_index; i++) {
- Dart_Handle value = Dart_ListGetAt(list, i);
- if (i > index) {
- buf->Printf(",");
- }
- FormatValueObj(buf, value);
- }
- buf->Printf("]}");
- return NULL;
-}
-
-
-static void FormatCallFrames(dart::TextBuffer* msg, Dart_StackTrace trace) {
- intptr_t trace_len = 0;
- Dart_Handle res = Dart_StackTraceLength(trace, &trace_len);
- ASSERT_NOT_ERROR(res);
- msg->Printf("\"callFrames\" : [ ");
- for (int i = 0; i < trace_len; i++) {
- Dart_ActivationFrame frame;
- res = Dart_GetActivationFrame(trace, i, &frame);
- ASSERT_NOT_ERROR(res);
- Dart_Handle func_name;
- Dart_Handle script_url;
- intptr_t line_number = 0;
- intptr_t library_id = 0;
- res = Dart_ActivationFrameInfo(
- frame, &func_name, &script_url, &line_number, &library_id);
- ASSERT_NOT_ERROR(res);
- ASSERT(Dart_IsString(func_name));
- msg->Printf("%s{\"functionName\":", (i > 0) ? "," : "");
- FormatEncodedString(msg, func_name);
- msg->Printf(",\"libraryId\": %"Pd",", library_id);
-
- ASSERT(Dart_IsString(script_url));
- msg->Printf("\"location\": { \"url\":");
- FormatEncodedString(msg, script_url);
- msg->Printf(",\"lineNumber\":%"Pd"},", line_number);
-
- Dart_Handle locals = Dart_GetLocalVariables(frame);
- ASSERT_NOT_ERROR(locals);
- msg->Printf("\"locals\":");
- FormatNamedValueList(msg, locals);
- msg->Printf("}");
- }
- msg->Printf("]");
-}
-
-
-void DebuggerConnectionHandler::HandleGetStackTraceCmd(const char* json_msg) {
- int msg_id = msgbuf_->MessageId();
- Dart_StackTrace trace;
- Dart_Handle res = Dart_GetStackTrace(&trace);
- ASSERT_NOT_ERROR(res);
- dart::TextBuffer msg(128);
- msg.Printf("{ \"id\": %d, \"result\": {", msg_id);
- FormatCallFrames(&msg, trace);
- msg.Printf("}}");
- SendMsg(&msg);
-}
-
-
-void DebuggerConnectionHandler::HandleSetBpCmd(const char* json_msg) {
- int msg_id = msgbuf_->MessageId();
- char* url_chars = msgbuf_->GetStringParam("url");
- ASSERT(url_chars != NULL);
- Dart_Handle url = Dart_NewString(url_chars);
- ASSERT_NOT_ERROR(url);
- free(url_chars);
- url_chars = NULL;
- intptr_t line_number = msgbuf_->GetIntParam("line");
- Dart_Handle bp_id = Dart_SetBreakpoint(url, line_number);
- if (Dart_IsError(bp_id)) {
- SendError(msg_id, Dart_GetError(bp_id));
- return;
- }
- ASSERT(Dart_IsInteger(bp_id));
- uint64_t bp_id_value;
- Dart_Handle res = Dart_IntegerToUint64(bp_id, &bp_id_value);
- ASSERT_NOT_ERROR(res);
- dart::TextBuffer msg(64);
- msg.Printf("{ \"id\": %d, \"result\": { \"breakpointId\": %"Pu64" }}",
- msg_id, bp_id_value);
- SendMsg(&msg);
-}
-
-
-void DebuggerConnectionHandler::HandlePauseOnExcCmd(const char* json_msg) {
- int msg_id = msgbuf_->MessageId();
- char* exc_chars = msgbuf_->GetStringParam("exceptions");
- Dart_ExceptionPauseInfo info = kNoPauseOnExceptions;
- if (strcmp(exc_chars, "none") == 0) {
- info = kNoPauseOnExceptions;
- } else if (strcmp(exc_chars, "all") == 0) {
- info = kPauseOnAllExceptions;
- } else if (strcmp(exc_chars, "unhandled") == 0) {
- info = kPauseOnUnhandledExceptions;
- } else {
- SendError(msg_id, "illegal value for parameter 'exceptions'");
- return;
- }
- Dart_Handle res = Dart_SetExceptionPauseInfo(info);
- ASSERT_NOT_ERROR(res);
- dart::TextBuffer msg(32);
- msg.Printf("{ \"id\": %d }", msg_id);
- SendMsg(&msg);
-}
-
-
-void DebuggerConnectionHandler::HandleRemBpCmd(const char* json_msg) {
- int msg_id = msgbuf_->MessageId();
- int bpt_id = msgbuf_->GetIntParam("breakpointId");
- Dart_Handle res = Dart_RemoveBreakpoint(bpt_id);
- if (Dart_IsError(res)) {
- SendError(msg_id, Dart_GetError(res));
- return;
- }
- dart::TextBuffer msg(32);
- msg.Printf("{ \"id\": %d }", msg_id);
- SendMsg(&msg);
-}
-
-
-void DebuggerConnectionHandler::HandleGetObjPropsCmd(const char* json_msg) {
- int msg_id = msgbuf_->MessageId();
- intptr_t obj_id = msgbuf_->GetIntParam("objectId");
- Dart_Handle obj = Dart_GetCachedObject(obj_id);
- if (Dart_IsError(obj)) {
- SendError(msg_id, Dart_GetError(obj));
- return;
- }
- dart::TextBuffer msg(64);
- msg.Printf("{\"id\":%d, \"result\":", msg_id);
- const char* err = FormatObjProps(&msg, obj);
- if (err != NULL) {
- SendError(msg_id, err);
- return;
- }
- msg.Printf("}");
- SendMsg(&msg);
-}
-
-
-void DebuggerConnectionHandler::HandleGetListCmd(const char* json_msg) {
- const intptr_t kDefaultSliceLength = 100;
- int msg_id = msgbuf_->MessageId();
- intptr_t obj_id = msgbuf_->GetIntParam("objectId");
- Dart_Handle list = Dart_GetCachedObject(obj_id);
- if (Dart_IsError(list)) {
- SendError(msg_id, Dart_GetError(list));
- return;
- }
- if (!Dart_IsList(list)) {
- SendError(msg_id, "object is not a list");
- return;
- }
- intptr_t list_length = 0;
- Dart_Handle res = Dart_ListLength(list, &list_length);
- if (Dart_IsError(res)) {
- SendError(msg_id, Dart_GetError(res));
- return;
- }
-
- intptr_t index = msgbuf_->GetIntParam("index");
- if (index < 0) {
- index = 0;
- } else if (index > list_length) {
- index = list_length;
- }
-
- // If no slice length is given, get only one element. If slice length
- // is given as 0, get entire list.
- intptr_t slice_length = msgbuf_->GetOptIntParam("length", 1);
- if (slice_length == 0) {
- slice_length = list_length - index;
- }
- if ((index + slice_length) > list_length) {
- slice_length = list_length - index;
- }
- ASSERT(slice_length >= 0);
- if (slice_length > kDefaultSliceLength) {
- slice_length = kDefaultSliceLength;
- }
- dart::TextBuffer msg(64);
- msg.Printf("{\"id\":%d, \"result\":", msg_id);
- if (slice_length == 1) {
- Dart_Handle value = Dart_ListGetAt(list, index);
- FormatRemoteObj(&msg, value);
- } else {
- FormatListSlice(&msg, list, list_length, index, slice_length);
- }
- msg.Printf("}");
- SendMsg(&msg);
-}
-
-
-void DebuggerConnectionHandler::HandleGetClassPropsCmd(const char* json_msg) {
- int msg_id = msgbuf_->MessageId();
- intptr_t cls_id = msgbuf_->GetIntParam("classId");
- dart::TextBuffer msg(64);
- msg.Printf("{\"id\":%d, \"result\":", msg_id);
- const char* err = FormatClassProps(&msg, cls_id);
- if (err != NULL) {
- SendError(msg_id, err);
- return;
- }
- msg.Printf("}");
- SendMsg(&msg);
-}
-
-
-void DebuggerConnectionHandler::HandleGetLibPropsCmd(const char* json_msg) {
- int msg_id = msgbuf_->MessageId();
- intptr_t lib_id = msgbuf_->GetIntParam("libraryId");
- dart::TextBuffer msg(64);
- msg.Printf("{\"id\":%d, \"result\":", msg_id);
- const char* err = FormatLibraryProps(&msg, lib_id);
- if (err != NULL) {
- SendError(msg_id, err);
- return;
- }
- msg.Printf("}");
- SendMsg(&msg);
-}
-
-
-void DebuggerConnectionHandler::HandleSetLibPropsCmd(const char* json_msg) {
- int msg_id = msgbuf_->MessageId();
- intptr_t lib_id = msgbuf_->GetIntParam("libraryId");
- const char* enable_request = msgbuf_->GetStringParam("debuggingEnabled");
- bool enable;
- if (strcmp(enable_request, "true") == 0) {
- enable = true;
- } else if (strcmp(enable_request, "false") == 0) {
- enable = false;
- } else {
- SendError(msg_id, "illegal argument for 'debuggingEnabled'");
- return;
- }
- Dart_Handle res = Dart_SetLibraryDebuggable(lib_id, enable);
- if (Dart_IsError(res)) {
- SendError(msg_id, Dart_GetError(res));
- return;
- }
- bool enabled = false;
- res = Dart_GetLibraryDebuggable(lib_id, &enabled);
- if (Dart_IsError(res)) {
- SendError(msg_id, Dart_GetError(res));
- return;
- }
- dart::TextBuffer msg(64);
- msg.Printf("{\"id\":%d, \"result\": {\"debuggingEnabled\": \"%s\"}}",
- msg_id,
- enabled ? "true" : "false");
- SendMsg(&msg);
-}
-
-
-void DebuggerConnectionHandler::HandleGetGlobalsCmd(const char* json_msg) {
- int msg_id = msgbuf_->MessageId();
- intptr_t lib_id = msgbuf_->GetIntParam("libraryId");
- dart::TextBuffer msg(64);
- msg.Printf("{\"id\":%d, \"result\": { \"globals\":", msg_id);
- Dart_Handle globals = Dart_GetGlobalVariables(lib_id);
- ASSERT_NOT_ERROR(globals);
- FormatNamedValueList(&msg, globals);
- msg.Printf("}}");
- SendMsg(&msg);
-}
-
-
-void DebuggerConnectionHandler::HandleUnknownMsg(const char* json_msg) {
- int msg_id = msgbuf_->MessageId();
- ASSERT(msg_id >= 0);
- SendError(msg_id, "unknown debugger command");
-}
-
-
void DebuggerConnectionHandler::HandleMessages() {
- static JSONDebuggerCommand debugger_commands[] = {
- { "resume", HandleResumeCmd },
- { "getLibraries", HandleGetLibrariesCmd },
- { "getClassProperties", HandleGetClassPropsCmd },
- { "getLibraryProperties", HandleGetLibPropsCmd },
- { "setLibraryProperties", HandleSetLibPropsCmd },
- { "getObjectProperties", HandleGetObjPropsCmd },
- { "getListElements", HandleGetListCmd },
- { "getGlobalVariables", HandleGetGlobalsCmd },
- { "getScriptURLs", HandleGetScriptURLsCmd },
- { "getScriptSource", HandleGetSourceCmd },
- { "getStackTrace", HandleGetStackTraceCmd },
- { "setBreakpoint", HandleSetBpCmd },
- { "setPauseOnException", HandlePauseOnExcCmd },
- { "removeBreakpoint", HandleRemBpCmd },
- { "stepInto", HandleStepIntoCmd },
- { "stepOut", HandleStepOutCmd },
- { "stepOver", HandleStepOverCmd },
+ static JSONDebuggerCommand generic_debugger_commands[] = {
+ { "interrupt", HandleInterruptCmd },
+ { "isolates", HandleIsolatesListCmd },
+ { "quit", HandleQuitCmd },
{ NULL, NULL }
};
for (;;) {
- SendQueuedMsgs();
+ // Read a message.
while (!msgbuf_->IsValidMessage() && msgbuf_->Alive()) {
msgbuf_->ReadData();
}
if (!msgbuf_->Alive()) {
return;
}
+
+ // Parse out the command portion from the message.
dart::JSONReader r(msgbuf_->buf());
bool found = r.Seek("command");
if (r.Error()) {
@@ -941,165 +202,217 @@
printf("'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;
- request_resume_ = false;
- while (debugger_commands[i].cmd_string != NULL) {
- if (r.IsStringLiteral(debugger_commands[i].cmd_string)) {
+ while (generic_debugger_commands[i].cmd_string != NULL) {
+ if (r.IsStringLiteral(generic_debugger_commands[i].cmd_string)) {
+ (*generic_debugger_commands[i].handler_function)(this);
is_handled = true;
- (*debugger_commands[i].handler_function)(msgbuf_->buf());
msgbuf_->PopMessage();
- if (request_resume_) {
- return;
- }
break;
}
i++;
}
if (!is_handled) {
+ // Check if this is an isolate specific command.
+ int32_t cmd_idx = DbgMessageQueue::LookupIsolateCommand(r.ValueChars(),
+ r.ValueLen());
+ if (cmd_idx != DbgMessageQueue::kInvalidCommand) {
+ // Get debug message queue corresponding to isolate.
+ // TODO(asiva): Need to read the isolate id, map it to the appropriate
+ // isolate and pass it down to GetIsolateMessageQueue to get the
+ // appropriate debug message queue.
+ DbgMessageQueue* queue = DbgMessageQueue::GetIsolateMessageQueue(NULL);
+ ASSERT(queue != NULL);
+ queue->AddMessage(cmd_idx, msgbuf_->buf(), r.EndOfObject(), debug_fd_);
+ msgbuf_->PopMessage();
+ continue;
+ }
+
+ // This is an unrecognized command, report error and move on to next.
printf("unrecognized command received: '%s'\n", msgbuf_->buf());
- HandleUnknownMsg(msgbuf_->buf());
+ HandleUnknownMsg();
msgbuf_->PopMessage();
}
}
}
+void DebuggerConnectionHandler::SendError(int debug_fd,
+ int msg_id,
+ const char* err_msg) {
+ dart::TextBuffer msg(64);
+ msg.Printf("{\"id\": %d, \"error\": \"Error: %s\"}", msg_id, err_msg);
+ SendMsg(debug_fd, &msg);
+}
+
+
+void DebuggerConnectionHandler::CloseDbgConnection() {
+ if (debug_fd_ >= 0) {
+ // TODO(hausner): need a Socket::Close() function.
+ }
+ if (msgbuf_ != NULL) {
+ delete msgbuf_;
+ msgbuf_ = NULL;
+ }
+ // TODO(hausner): Need to tell the VM debugger object to remove all
+ // breakpoints.
+}
+
+
+void DebuggerConnectionHandler::StartHandler(const char* address,
+ int port_number) {
+ MonitorLocker ml(&handler_lock_);
+ if (listener_fd_ != -1) {
+ return; // The debugger connection handler was already started.
+ }
+
+ // First setup breakpoint, exception and delayed breakpoint handlers.
+ DbgMessageQueue::Initialize();
+
+ // 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);
+ listener_fd_ = ServerSocket::CreateBindListen(address, port_number, 1);
+ DebuggerConnectionImpl::StartHandler(port_number);
+}
+
+
void DebuggerConnectionHandler::WaitForConnection() {
- MonitorLocker ml(&is_connected_);
+ MonitorLocker ml(&handler_lock_);
while (!IsConnected()) {
- dart::Monitor::WaitResult res = ml.Wait(dart::Monitor::kNoTimeout);
+ dart::Monitor::WaitResult res = ml.Wait();
ASSERT(res == dart::Monitor::kNotified);
}
}
-void DebuggerConnectionHandler::SendBreakpointEvent(Dart_StackTrace trace) {
- dart::TextBuffer msg(128);
- msg.Printf("{ \"event\": \"paused\", \"params\": { ");
- msg.Printf("\"reason\": \"breakpoint\", ");
- FormatCallFrames(&msg, trace);
- msg.Printf("}}");
- SendMsg(&msg);
+void DebuggerConnectionHandler::SendMsg(int debug_fd, dart::TextBuffer* msg) {
+ MonitorLocker ml(&handler_lock_);
+ SendMsgHelper(debug_fd, msg);
}
-void DebuggerConnectionHandler::BreakpointHandler(Dart_Breakpoint bpt,
- Dart_StackTrace trace) {
- WaitForConnection();
- Dart_EnterScope();
- SendQueuedMsgs();
- SendBreakpointEvent(trace);
- HandleMessages();
- if (!msgbuf_->Alive()) {
- CloseDbgConnection();
- }
- Dart_ExitScope();
+void DebuggerConnectionHandler::BroadcastMsg(dart::TextBuffer* msg) {
+ MonitorLocker ml(&handler_lock_);
+ // 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::IsolateEventHandler(Dart_Isolate isolate,
- Dart_IsolateEvent kind) {
- WaitForConnection();
-#if 0
- if (kind == kCreated) {
- printf("Isolate created %p\n", isolate);
- } else if (kind == kInterrupted) {
- printf("Isolate interrupted %p\n", isolate);
- } else if (kind == kShutdown) {
- printf("Isolate shutdown %p\n", isolate);
+void DebuggerConnectionHandler::SendMsgHelper(int debug_fd,
+ dart::TextBuffer* msg) {
+ ASSERT(debug_fd >= 0);
+ ASSERT(IsValidJSON(msg->buf()));
+ // 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.
+ dart::Monitor sleep;
+ while (remaining > 0) {
+ intptr_t piece_len = remaining;
+ if (piece_len > max_piece_len) {
+ piece_len = max_piece_len;
+ }
+ intptr_t written =
+ Socket::Write(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;
}
-#endif
+ intptr_t bytes_written = Socket::Write(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::SendExceptionEvent(
- Dart_Handle exception,
- Dart_StackTrace stack_trace) {
- intptr_t exception_id = Dart_CacheObject(exception);
- ASSERT(exception_id >= 0);
- dart::TextBuffer msg(128);
- msg.Printf("{ \"event\": \"paused\", \"params\": {");
- msg.Printf("\"reason\": \"exception\", ");
- msg.Printf("\"exception\":");
- FormatRemoteObj(&msg, exception);
- msg.Printf(", ");
- FormatCallFrames(&msg, stack_trace);
- msg.Printf("}}");
- SendMsg(&msg);
+void DebuggerConnectionHandler::AcceptDbgConnection(int debug_fd) {
+ AddNewDebuggerConnection(debug_fd);
+ {
+ 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::ExceptionThrownHandler(
- Dart_Handle exception,
- Dart_StackTrace stack_trace) {
- WaitForConnection();
- Dart_EnterScope();
- SendQueuedMsgs();
- SendExceptionEvent(exception, stack_trace);
- HandleMessages();
- if (!msgbuf_->Alive()) {
- CloseDbgConnection();
- }
- Dart_ExitScope();
+void DebuggerConnectionHandler::HandleInterruptCmd(
+ DebuggerConnectionHandler* handler) {
+ int msg_id = handler->MessageId();
+ ASSERT(msg_id >= 0);
+ SendError(handler->debug_fd(), msg_id, "interrupt command unimplemented");
}
-void DebuggerConnectionHandler::BptResolvedHandler(intptr_t bp_id,
- Dart_Handle url,
- intptr_t line_number) {
- Dart_EnterScope();
- dart::TextBuffer msg(128);
- msg.Printf("{ \"event\": \"breakpointResolved\", \"params\": {");
- msg.Printf("\"breakpointId\": %"Pd", \"url\":", bp_id);
- FormatEncodedString(&msg, url);
- msg.Printf(",\"line\": %"Pd" }}", line_number);
- QueueMsg(&msg);
- Dart_ExitScope();
+void DebuggerConnectionHandler::HandleIsolatesListCmd(
+ DebuggerConnectionHandler* handler) {
+ int msg_id = handler->MessageId();
+ ASSERT(msg_id >= 0);
+ SendError(handler->debug_fd(), msg_id, "isolate list command unimplemented");
}
-void DebuggerConnectionHandler::AcceptDbgConnection(int debugger_fd) {
- debugger_fd_ = debugger_fd;
- ASSERT(msgbuf_ == NULL);
- msgbuf_ = new MessageBuffer(debugger_fd_);
- {
- MonitorLocker ml(&is_connected_);
- ml.Notify();
- }
+void DebuggerConnectionHandler::HandleQuitCmd(
+ DebuggerConnectionHandler* handler) {
+ int msg_id = handler->MessageId();
+ ASSERT(msg_id >= 0);
+ SendError(handler->debug_fd(), msg_id, "quit command unimplemented");
}
-void DebuggerConnectionHandler::CloseDbgConnection() {
- if (debugger_fd_ >= 0) {
- // TODO(hausner): need a Socket::Close() function.
- }
- if (msgbuf_ != NULL) {
- delete msgbuf_;
- msgbuf_ = NULL;
- }
- // TODO(hausner): Need to tell the VM debugger object to remove all
- // breakpoints.
+void DebuggerConnectionHandler::AddNewDebuggerConnection(int 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::StartHandler(const char* address,
- int port_number) {
- if (handler_started_) {
- return;
- }
- ASSERT(listener_fd_ == -1);
- listener_fd_ = ServerSocket::CreateBindListen(address, port_number, 1);
+void DebuggerConnectionHandler::RemoveDebuggerConnection(int 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;
+}
- handler_started_ = true;
- DebuggerConnectionImpl::StartHandler(port_number);
- Dart_SetIsolateEventHandler(IsolateEventHandler);
- Dart_SetBreakpointHandler(BreakpointHandler);
- Dart_SetBreakpointResolvedHandler(BptResolvedHandler);
- Dart_SetExceptionThrownHandler(ExceptionThrownHandler);
+
+DebuggerConnectionHandler*
+DebuggerConnectionHandler::GetDebuggerConnectionHandler(int 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;
}
-DebuggerConnectionHandler::~DebuggerConnectionHandler() {
- CloseDbgConnection();
+bool DebuggerConnectionHandler::IsConnected() {
+ // TODO(asiva): Support multiple debugger connections.
+ // Return true if a connection has been established.
+ return singleton_handler != NULL;
}
« no previous file with comments | « runtime/bin/dbg_connection.h ('k') | runtime/bin/dbg_connection_linux.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698