diff --git a/src/node.cc b/src/node.cc index 648c4d1b91..3f00c5313f 100644 --- a/src/node.cc +++ b/src/node.cc @@ -62,6 +62,8 @@ static Persistent emit_symbol; static int option_end_index = 0; static bool use_debug_agent = false; +static bool debug_wait_connect = false; +static int debug_port=5858; static ev_async eio_want_poll_notifier; @@ -909,6 +911,7 @@ void FatalException(TryCatch &try_catch) { static ev_async debug_watcher; +volatile static bool debugger_msg_pending = false; static void DebugMessageCallback(EV_P_ ev_async *watcher, int revents) { HandleScope scope; @@ -923,9 +926,49 @@ static void DebugMessageDispatch(void) { // Send a signal to our main thread saying that it should enter V8 to // handle the message. + debugger_msg_pending = true; ev_async_send(EV_DEFAULT_UC_ &debug_watcher); } +static Handle CheckBreak(const Arguments& args) { + HandleScope scope; + + // TODO FIXME This function is a hack to wait until V8 is ready to accept + // commands. There seems to be a bug in EnableAgent( _ , _ , true) which + // makes it unusable here. Ideally we'd be able to bind EnableAgent and + // get it to halt until Eclipse connects. + + if (!debug_wait_connect) + return Undefined(); + + printf("Waiting for remote debugger connection...\n"); + + const int halfSecond = 50; + const int tenMs=10000; + debugger_msg_pending = false; + for (;;) { + if (debugger_msg_pending) { + Debug::DebugBreak(); + Debug::ProcessDebugMessages(); + debugger_msg_pending = false; + + // wait for 500 msec of silence from remote debugger + int cnt = halfSecond; + while (cnt --) { + debugger_msg_pending = false; + usleep(tenMs); + if (debugger_msg_pending) { + debugger_msg_pending = false; + cnt = halfSecond; + } + } + break; + } + usleep(tenMs); + } + return Undefined(); +} + static void Load(int argc, char *argv[]) { HandleScope scope; @@ -995,6 +1038,7 @@ static void Load(int argc, char *argv[]) { NODE_SET_METHOD(process, "dlopen", DLOpen); NODE_SET_METHOD(process, "kill", Kill); NODE_SET_METHOD(process, "memoryUsage", MemoryUsage); + NODE_SET_METHOD(process, "checkBreak", CheckBreak); // Assign the EventEmitter. It was created in main(). process->Set(String::NewSymbol("EventEmitter"), @@ -1067,6 +1111,7 @@ static void Load(int argc, char *argv[]) { // Node's I/O bindings may want to replace 'f' with their own function. Local args[1] = { Local::New(process) }; + f->Call(global, 1, args); #ifndef NDEBUG @@ -1077,12 +1122,43 @@ static void Load(int argc, char *argv[]) { #endif } +static void PrintHelp(); + +static void ParseDebugOpt(const char* arg) { + const char *p = 0; + + use_debug_agent = true; + if (!strcmp (arg, "--debug-brk")) { + debug_wait_connect = true; + return; + } else if (!strcmp(arg, "--debug")) { + return; + } else if (strstr(arg, "--debug-brk=") == arg) { + debug_wait_connect = true; + p = 1 + strchr(arg, '='); + debug_port = atoi(p); + } else if (strstr(arg, "--debug=") == arg) { + p = 1 + strchr(arg, '='); + debug_port = atoi(p); + } + if (p && debug_port > 1024 && debug_port < 65536) + return; + + fprintf(stderr, "Bad debug option.\n"); + if (p) fprintf(stderr, "Debug port must be in range 1025 to 65535.\n"); + + PrintHelp(); + exit(1); +} + static void PrintHelp() { printf("Usage: node [options] script.js [arguments] \n" - " -v, --version print node's version\n" - " --debug enable remote debugging\n" // TODO specify port - " --cflags print pre-processor and compiler flags\n" - " --v8-options print v8 command line options\n\n" + " -v, --version print node's version\n" + " --debug[=port] enable remote debugging via given TCP port\n" + " --debug-brk[=port] as above, but break in node.js and\n" + " wait for remote debugger to connect\n" + " --cflags print pre-processor and compiler flags\n" + " --v8-options print v8 command line options\n\n" "Documentation can be found at http://nodejs.org/api.html" " or with 'man node'\n"); } @@ -1092,9 +1168,9 @@ static void ParseArgs(int *argc, char **argv) { // TODO use parse opts for (int i = 1; i < *argc; i++) { const char *arg = argv[i]; - if (strcmp(arg, "--debug") == 0) { + if (strstr(arg, "--debug") == arg) { + ParseDebugOpt(arg); argv[i] = reinterpret_cast(""); - use_debug_agent = true; option_end_index = i; } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) { printf("%s\n", NODE_VERSION); @@ -1191,12 +1267,12 @@ int main(int argc, char *argv[]) { ev_unref(EV_DEFAULT_UC); // Start the debug thread and it's associated TCP server on port 5858. - bool r = Debug::EnableAgent("node " NODE_VERSION, 5858); + bool r = Debug::EnableAgent("node " NODE_VERSION, node::debug_port); + // Crappy check that everything went well. FIXME assert(r); - // Print out some information. REMOVEME - printf("debugger listening on port 5858\n" - "Use 'd8 --remote_debugger' to access it.\n"); + // Print out some information. + printf("debugger listening on port %d\n", node::debug_port); } // Create the one and only Context. diff --git a/src/node.js b/src/node.js index 66b9fe67e3..7ad28f2d86 100644 --- a/src/node.js +++ b/src/node.js @@ -926,7 +926,10 @@ Module.prototype._loadContent = function (content, filename) { try { var compiledWrapper = process.compile(wrapper, filename); - compiledWrapper.apply(self.exports, [self.exports, require, self, filename, path.dirname(filename)]); + var dirName = path.dirname(filename); + if (filename === process.argv[1]) + process.checkBreak(); + compiledWrapper.apply(self.exports, [self.exports, require, self, filename, dirName]); } catch (e) { return e; }