|
@ -62,6 +62,8 @@ static Persistent<String> emit_symbol; |
|
|
|
|
|
|
|
|
static int option_end_index = 0; |
|
|
static int option_end_index = 0; |
|
|
static bool use_debug_agent = false; |
|
|
static bool use_debug_agent = false; |
|
|
|
|
|
static bool debug_wait_connect = false; |
|
|
|
|
|
static int debug_port=5858; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static ev_async eio_want_poll_notifier; |
|
|
static ev_async eio_want_poll_notifier; |
|
@ -909,6 +911,7 @@ void FatalException(TryCatch &try_catch) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static ev_async debug_watcher; |
|
|
static ev_async debug_watcher; |
|
|
|
|
|
volatile static bool debugger_msg_pending = false; |
|
|
|
|
|
|
|
|
static void DebugMessageCallback(EV_P_ ev_async *watcher, int revents) { |
|
|
static void DebugMessageCallback(EV_P_ ev_async *watcher, int revents) { |
|
|
HandleScope scope; |
|
|
HandleScope scope; |
|
@ -923,9 +926,49 @@ static void DebugMessageDispatch(void) { |
|
|
|
|
|
|
|
|
// Send a signal to our main thread saying that it should enter V8 to
|
|
|
// Send a signal to our main thread saying that it should enter V8 to
|
|
|
// handle the message.
|
|
|
// handle the message.
|
|
|
|
|
|
debugger_msg_pending = true; |
|
|
ev_async_send(EV_DEFAULT_UC_ &debug_watcher); |
|
|
ev_async_send(EV_DEFAULT_UC_ &debug_watcher); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static Handle<Value> 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[]) { |
|
|
static void Load(int argc, char *argv[]) { |
|
|
HandleScope scope; |
|
|
HandleScope scope; |
|
@ -995,6 +1038,7 @@ static void Load(int argc, char *argv[]) { |
|
|
NODE_SET_METHOD(process, "dlopen", DLOpen); |
|
|
NODE_SET_METHOD(process, "dlopen", DLOpen); |
|
|
NODE_SET_METHOD(process, "kill", Kill); |
|
|
NODE_SET_METHOD(process, "kill", Kill); |
|
|
NODE_SET_METHOD(process, "memoryUsage", MemoryUsage); |
|
|
NODE_SET_METHOD(process, "memoryUsage", MemoryUsage); |
|
|
|
|
|
NODE_SET_METHOD(process, "checkBreak", CheckBreak); |
|
|
|
|
|
|
|
|
// Assign the EventEmitter. It was created in main().
|
|
|
// Assign the EventEmitter. It was created in main().
|
|
|
process->Set(String::NewSymbol("EventEmitter"), |
|
|
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.
|
|
|
// Node's I/O bindings may want to replace 'f' with their own function.
|
|
|
|
|
|
|
|
|
Local<Value> args[1] = { Local<Value>::New(process) }; |
|
|
Local<Value> args[1] = { Local<Value>::New(process) }; |
|
|
|
|
|
|
|
|
f->Call(global, 1, args); |
|
|
f->Call(global, 1, args); |
|
|
|
|
|
|
|
|
#ifndef NDEBUG |
|
|
#ifndef NDEBUG |
|
@ -1077,12 +1122,43 @@ static void Load(int argc, char *argv[]) { |
|
|
#endif |
|
|
#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() { |
|
|
static void PrintHelp() { |
|
|
printf("Usage: node [options] script.js [arguments] \n" |
|
|
printf("Usage: node [options] script.js [arguments] \n" |
|
|
" -v, --version print node's version\n" |
|
|
" -v, --version print node's version\n" |
|
|
" --debug enable remote debugging\n" // TODO specify port
|
|
|
" --debug[=port] enable remote debugging via given TCP port\n" |
|
|
" --cflags print pre-processor and compiler flags\n" |
|
|
" --debug-brk[=port] as above, but break in node.js and\n" |
|
|
" --v8-options print v8 command line options\n\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" |
|
|
"Documentation can be found at http://nodejs.org/api.html" |
|
|
" or with 'man node'\n"); |
|
|
" or with 'man node'\n"); |
|
|
} |
|
|
} |
|
@ -1092,9 +1168,9 @@ static void ParseArgs(int *argc, char **argv) { |
|
|
// TODO use parse opts
|
|
|
// TODO use parse opts
|
|
|
for (int i = 1; i < *argc; i++) { |
|
|
for (int i = 1; i < *argc; i++) { |
|
|
const char *arg = argv[i]; |
|
|
const char *arg = argv[i]; |
|
|
if (strcmp(arg, "--debug") == 0) { |
|
|
if (strstr(arg, "--debug") == arg) { |
|
|
|
|
|
ParseDebugOpt(arg); |
|
|
argv[i] = reinterpret_cast<const char*>(""); |
|
|
argv[i] = reinterpret_cast<const char*>(""); |
|
|
use_debug_agent = true; |
|
|
|
|
|
option_end_index = i; |
|
|
option_end_index = i; |
|
|
} else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) { |
|
|
} else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) { |
|
|
printf("%s\n", NODE_VERSION); |
|
|
printf("%s\n", NODE_VERSION); |
|
@ -1191,12 +1267,12 @@ int main(int argc, char *argv[]) { |
|
|
ev_unref(EV_DEFAULT_UC); |
|
|
ev_unref(EV_DEFAULT_UC); |
|
|
|
|
|
|
|
|
// Start the debug thread and it's associated TCP server on port 5858.
|
|
|
// 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
|
|
|
// Crappy check that everything went well. FIXME
|
|
|
assert(r); |
|
|
assert(r); |
|
|
// Print out some information. REMOVEME
|
|
|
// Print out some information.
|
|
|
printf("debugger listening on port 5858\n" |
|
|
printf("debugger listening on port %d\n", node::debug_port); |
|
|
"Use 'd8 --remote_debugger' to access it.\n"); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Create the one and only Context.
|
|
|
// Create the one and only Context.
|
|
|