Fork out to debugger on debugger statements
Also implement continue in Client.
This commit is contained in:
parent
4e81cf7def
commit
0dcbe3f74a
@ -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";
|
var helpMessage = "Commands: scripts, backtrace, version, eval, help, quit";
|
||||||
|
|
||||||
|
|
||||||
@ -223,18 +230,33 @@ function startInterface() {
|
|||||||
i.write(chunk);
|
i.write(chunk);
|
||||||
});
|
});
|
||||||
|
|
||||||
var prompt = '> ';
|
var prompt = 'debug> ';
|
||||||
|
|
||||||
i.setPrompt(prompt);
|
i.setPrompt(prompt);
|
||||||
i.prompt();
|
i.prompt();
|
||||||
|
|
||||||
i.on('SIGINT', function() {
|
var quitTried = false;
|
||||||
|
|
||||||
|
function tryQuit() {
|
||||||
|
if (quitTried) return;
|
||||||
|
quitTried = true;
|
||||||
i.close();
|
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) {
|
i.on('line', function(cmd) {
|
||||||
if (cmd == 'quit') {
|
if (cmd == 'quit') {
|
||||||
process.exit(0);
|
tryQuit();
|
||||||
} else if (/^help/.test(cmd)) {
|
} else if (/^help/.test(cmd)) {
|
||||||
console.log(helpMessage);
|
console.log(helpMessage);
|
||||||
i.prompt();
|
i.prompt();
|
||||||
@ -251,6 +273,12 @@ function startInterface() {
|
|||||||
i.prompt();
|
i.prompt();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
} else if ('continue' == cmd || 'c' == cmd) {
|
||||||
|
c.reqContinue(function (res) {
|
||||||
|
console.log(res);
|
||||||
|
i.prompt();
|
||||||
|
});
|
||||||
|
|
||||||
} else if (/^scripts/.test(cmd)) {
|
} else if (/^scripts/.test(cmd)) {
|
||||||
c.reqScripts(function (res) {
|
c.reqScripts(function (res) {
|
||||||
var text = res.map(function (x) { return x.text; });
|
var text = res.map(function (x) { return x.text; });
|
||||||
|
@ -160,6 +160,8 @@ Interface.prototype._refreshLine = function() {
|
|||||||
|
|
||||||
|
|
||||||
Interface.prototype.close = function(d) {
|
Interface.prototype.close = function(d) {
|
||||||
|
if (this._closing) return;
|
||||||
|
this._closing = true;
|
||||||
if (this.enabled) {
|
if (this.enabled) {
|
||||||
tty.setRawMode(false);
|
tty.setRawMode(false);
|
||||||
}
|
}
|
||||||
|
59
src/node.cc
59
src/node.cc
@ -17,6 +17,11 @@
|
|||||||
#include <pwd.h> /* getpwnam() */
|
#include <pwd.h> /* getpwnam() */
|
||||||
#include <grp.h> /* getgrnam() */
|
#include <grp.h> /* getgrnam() */
|
||||||
|
|
||||||
|
// waitpid
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
|
||||||
#include <node_buffer.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[]) {
|
int Start(int argc, char *argv[]) {
|
||||||
// Hack aroung with the argv pointer. Used for process.title = "blah".
|
// Hack aroung with the argv pointer. Used for process.title = "blah".
|
||||||
argv = node::Platform::SetupArgs(argc, argv);
|
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 the --debug flag was specified then initialize the debug thread.
|
||||||
if (node::use_debug_agent) {
|
if (node::use_debug_agent) {
|
||||||
EnableDebug(debug_wait_connect);
|
// XXX: only use if debug flag enabled?
|
||||||
|
Debug::SetDebugEventListener(HandleDebugEvent);
|
||||||
} else {
|
} else {
|
||||||
RegisterSignalHandler(SIGUSR1, EnableDebugSignalHandler);
|
RegisterSignalHandler(SIGUSR1, EnableDebugSignalHandler);
|
||||||
ev_async_init(&enable_debug, EnableDebug2);
|
ev_async_init(&enable_debug, EnableDebug2);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user