Browse Source

Fork out to debugger on debugger statements

Also implement continue in Client.
v0.7.4-release
Ryan Dahl 14 years ago
parent
commit
0dcbe3f74a
  1. 36
      lib/_debugger.js
  2. 2
      lib/readline.js
  3. 59
      src/node.cc

36
lib/_debugger.js

@ -212,6 +212,13 @@ Client.prototype.reqScripts = function(cb) {
};
Client.prototype.reqContinue = function(cb) {
this.req({ command: 'continue' } , function (res) {
if (cb) cb(res.body);
});
};
var helpMessage = "Commands: scripts, backtrace, version, eval, help, quit";
@ -223,18 +230,33 @@ function startInterface() {
i.write(chunk);
});
var prompt = '> ';
var prompt = 'debug> ';
i.setPrompt(prompt);
i.prompt();
i.on('SIGINT', function() {
var quitTried = false;
function tryQuit() {
if (quitTried) return;
quitTried = true;
i.close();
});
console.log("debug done\n");
if (c.writable) {
c.reqContinue(function (res) {
process.exit(0);
});
} else {
process.exit(0);
}
}
i.on('SIGINT', tryQuit);
i.on('close', tryQuit);
i.on('line', function(cmd) {
if (cmd == 'quit') {
process.exit(0);
tryQuit();
} else if (/^help/.test(cmd)) {
console.log(helpMessage);
i.prompt();
@ -251,6 +273,12 @@ function startInterface() {
i.prompt();
});
} else if ('continue' == cmd || 'c' == cmd) {
c.reqContinue(function (res) {
console.log(res);
i.prompt();
});
} else if (/^scripts/.test(cmd)) {
c.reqScripts(function (res) {
var text = res.map(function (x) { return x.text; });

2
lib/readline.js

@ -160,6 +160,8 @@ Interface.prototype._refreshLine = function() {
Interface.prototype.close = function(d) {
if (this._closing) return;
this._closing = true;
if (this.enabled) {
tty.setRawMode(false);
}

59
src/node.cc

@ -17,6 +17,11 @@
#include <pwd.h> /* getpwnam() */
#include <grp.h> /* getgrnam() */
// waitpid
#include <sys/types.h>
#include <sys/wait.h>
#include "platform.h"
#include <node_buffer.h>
@ -1908,6 +1913,57 @@ static int RegisterSignalHandler(int signal, void (*handler)(int)) {
}
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);
@ -2022,7 +2078,8 @@ int Start(int argc, char *argv[]) {
// If the --debug flag was specified then initialize the debug thread.
if (node::use_debug_agent) {
EnableDebug(debug_wait_connect);
// XXX: only use if debug flag enabled?
Debug::SetDebugEventListener(HandleDebugEvent);
} else {
RegisterSignalHandler(SIGUSR1, EnableDebugSignalHandler);
ev_async_init(&enable_debug, EnableDebug2);

Loading…
Cancel
Save