var net = require('net');
var readline = require('readline');
var inherits = require('util').inherits;
+var spawn = require('child_process').spawn;
exports.port = 5858;
-exports.start = function (pid) {
- if (pid) {
- process.kill(pid, "SIGUSR1");
- setTimeout(tryConnect, 100);
- } else {
- tryConnect();
- }
+exports.start = function () {
+ startInterface();
};
var c;
+var term;
+
+function trySpawn(cb) {
+ var args = process.argv.slice(2);
+ args.unshift('--debug-brk');
+
+ console.log(args);
-function tryConnect() {
+ var child = spawn(process.execPath, args, {
+ customFds: [0, 1, 2]
+ });
+
+ setTimeout(function () {
+ tryConnect(cb);
+ }, 1000);
+}
+
+function tryConnect(cb) {
c = new Client();
process.stdout.write("connecting...");
c.connect(exports.port);
- c.on('ready', function () {
+ c.once('ready', function () {
process.stdout.write("ok\r\n");
- startInterface();
+ if (cb) cb();
+ });
+
+ c.on('close', function () {
+ process.exit(0);
});
+ c.on('unhandledResponse', function (res) {
+ console.log("\r\nunhandled res:");
+ console.log(res);
+ term.prompt();
+ });
+
+ c.on('break', function (res) {
+ var result = '';
+ if (res.body.breakpoints) {
+ result += 'breakpoint';
+ if (res.body.breakpoints.length > 1) {
+ result += 's';
+ }
+ result += ' #';
+ for (var i = 0; i < res.body.breakpoints.length; i++) {
+ if (i > 0) {
+ result += ', #';
+ }
+ result += res.body.breakpoints[i];
+ }
+ } else {
+ result += 'break';
+ }
+ result += ' in ';
+ result += res.body.invocationText;
+ result += ', ';
+ result += SourceInfo(res.body);
+ result += '\n';
+ result += SourceUnderline(res.body.sourceLineText, res.body.sourceColumn);
+
+ c.currentSourceLine = res.body.sourceLine;
+ c.currentFrame = 0;
+ c.currentScript = res.body.script.name;
+
+ console.log(result);
+
+ term.prompt();
+ });
}
//
this.emit('ready');
} else if (res.body && res.body.event == 'break') {
this.emit('break', res.body);
+ } else if (res.body && res.body.event == 'afterCompile') {
+ this.emit('afterCompile', res.body);
} else if (cb) {
this._reqCallbacks.splice(i, 1);
cb(res.body);
-
-
function startInterface() {
- var term = readline.createInterface(process.stdout);
+ term = readline.createInterface(process.stdout);
+
var stdin = process.openStdin();
stdin.addListener('data', function(chunk) {
term.write(chunk);
term.on('SIGINT', tryQuit);
term.on('close', tryQuit);
- c.on('close', function () {
- process.exit(0);
- });
term.on('line', function(cmd) {
if (cmd == 'quit' || cmd == 'q' || cmd == 'exit') {
tryQuit();
+
+ } else if (/^r(un)?/.test(cmd)) {
+ trySpawn();
+
} else if (/^help/.test(cmd)) {
console.log(helpMessage);
term.prompt();
term.prompt();
}
});
-
- c.on('unhandledResponse', function (res) {
- console.log("\r\nunhandled res:");
- console.log(res);
- term.prompt();
- });
-
- c.on('break', function (res) {
- var result = '';
- if (res.body.breakpoints) {
- result += 'breakpoint';
- if (res.body.breakpoints.length > 1) {
- result += 's';
- }
- result += ' #';
- for (var i = 0; i < res.body.breakpoints.length; i++) {
- if (i > 0) {
- result += ', #';
- }
- result += res.body.breakpoints[i];
- }
- } else {
- result += 'break';
- }
- result += ' in ';
- result += res.body.invocationText;
- result += ', ';
- result += SourceInfo(res.body);
- result += '\n';
- result += SourceUnderline(res.body.sourceLineText, res.body.sourceColumn);
-
- c.currentSourceLine = res.body.sourceLine;
- c.currentFrame = 0;
- c.currentScript = res.body.script.name;
-
- console.log(result);
-
- term.prompt();
- });
}
#include <pwd.h> /* getpwnam() */
#include <grp.h> /* getgrnam() */
-// waitpid
-#include <sys/types.h>
-#include <sys/wait.h>
-
-
#include "platform.h"
#include <node_buffer.h>
static bool need_tick_cb;
static Persistent<String> tick_callback_sym;
-static ev_async enable_debug;
static ev_async eio_want_poll_notifier;
static ev_async eio_done_poll_notifier;
static ev_idle eio_poller;
}
-static void EnableDebugSignalHandler(int signal) {
- // can't do much here, marshal this back into the main thread where we'll
- // enable the debugger.
- ev_async_send(EV_DEFAULT_UC_ &enable_debug);
-}
-
-
-static void EnableDebug(bool wait_connect) {
- // Start the debug thread and it's associated TCP server on port 5858.
- bool r = Debug::EnableAgent("node " NODE_VERSION, debug_port);
-
- if (wait_connect) {
- // Set up an empty handler so v8 will not continue until a debugger
- // attaches. This is the same behavior as Debug::EnableAgent(_,_,true)
- // except we don't break at the beginning of the script.
- // see Debugger::StartAgent in debug.cc of v8/src
- Debug::SetMessageHandler2(node::DebugBreakMessageHandler);
- }
-
- // Crappy check that everything went well. FIXME
- assert(r);
-
- // Print out some information.
- fprintf(stderr, "debugger listening on port %d\r\n", debug_port);
-}
-
-
-static void EnableDebug2(EV_P_ ev_async *watcher, int revents) {
- assert(watcher == &enable_debug);
- assert(revents == EV_ASYNC);
- EnableDebug(false);
-}
-
-
-
static int RegisterSignalHandler(int signal, void (*handler)(int)) {
struct sigaction sa;
}
-static bool debugger_slave_running = false;
-
-static void HandleDebugEvent(DebugEvent event,
- Handle<Object> exec_state,
- Handle<Object> event_data,
- Handle<Value> data) {
- HandleScope scope;
-
- if (debugger_slave_running) return;
-
- if (event != Break) {
- return;
- }
-
- // Then we take one of two actions
- // 1. Inspect the environ variable NODE_DEBUG_PROG; if it is not empty //
- // then start it. (TODO)
- // 2. Start the built-in debugger.
-
-
- size_t size = 2*PATH_MAX;
- char node_path[size];
- OS::GetExecutablePath(node_path, &size);
-
- int pid = vfork();
-
- if (pid == -1) {
- perror("vfork()");
- return;
- }
-
- if (pid == 0) {
- // Child process
- char *argv[] = { node_path, "debug", NULL };
- execvp(node_path, argv);
- perror("execvp()");
- _exit(127);
- }
-
- debugger_slave_running = true;
-
- // We've hit some debugger event. First we will enable the debugger agent.
- EnableDebug(true);
-
- // TODO probably need to waitpid here or something to avoid zombies.
- // int status;
- // waitpid(pid, &status, 0);
- //Debug::DebugBreak();
-}
-
-
int Start(int argc, char *argv[]) {
// Hack aroung with the argv pointer. Used for process.title = "blah".
argv = node::Platform::SetupArgs(argc, argv);
V8::SetFatalErrorHandler(node::OnFatalError);
-
- // Initialize the async watcher for receiving messages from the debug
- // thread and marshal it into the main thread. DebugMessageCallback()
- // is called from the main thread to execute a random bit of javascript
- // - which will give V8 control so it can handle whatever new message
- // had been received on the debug thread.
- ev_async_init(&node::debug_watcher, node::DebugMessageCallback);
- ev_set_priority(&node::debug_watcher, EV_MAXPRI);
- // Set the callback DebugMessageDispatch which is called from the debug
- // thread.
- Debug::SetDebugMessageDispatchHandler(node::DebugMessageDispatch);
- // Start the async watcher.
- ev_async_start(EV_DEFAULT_UC_ &node::debug_watcher);
- // unref it so that we exit the event loop despite it being active.
- ev_unref(EV_DEFAULT_UC);
-
-
// If the --debug flag was specified then initialize the debug thread.
if (node::use_debug_agent) {
- // XXX: only use if debug flag enabled?
- Debug::SetDebugEventListener(HandleDebugEvent);
- } else {
- RegisterSignalHandler(SIGUSR1, EnableDebugSignalHandler);
- ev_async_init(&enable_debug, EnableDebug2);
- ev_async_start(EV_DEFAULT_UC_ &enable_debug);
+ // Initialize the async watcher for receiving messages from the debug
+ // thread and marshal it into the main thread. DebugMessageCallback()
+ // is called from the main thread to execute a random bit of javascript
+ // - which will give V8 control so it can handle whatever new message
+ // had been received on the debug thread.
+ ev_async_init(&node::debug_watcher, node::DebugMessageCallback);
+ ev_set_priority(&node::debug_watcher, EV_MAXPRI);
+ // Set the callback DebugMessageDispatch which is called from the debug
+ // thread.
+ Debug::SetDebugMessageDispatchHandler(node::DebugMessageDispatch);
+ // Start the async watcher.
+ ev_async_start(EV_DEFAULT_UC_ &node::debug_watcher);
+ // unref it so that we exit the event loop despite it being active.
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, node::debug_port);
+ if (node::debug_wait_connect) {
+ // Set up an empty handler so v8 will not continue until a debugger
+ // attaches. This is the same behavior as Debug::EnableAgent(_,_,true)
+ // except we don't break at the beginning of the script.
+ // see Debugger::StartAgent in debug.cc of v8/src
+ Debug::SetMessageHandler2(node::DebugBreakMessageHandler);
+ }
+
+ // Crappy check that everything went well. FIXME
+ assert(r);
+ // Print out some information.
+ printf("debugger listening on port %d\n", node::debug_port);
}
// Create the one and only Context.