#ifdef __POSIX__
+static volatile sig_atomic_t caught_early_debug_signal;
+
+
+static void EarlyDebugSignalHandler(int signo) {
+ caught_early_debug_signal = 1;
+}
+
+
+static void InstallEarlyDebugSignalHandler() {
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = EarlyDebugSignalHandler;
+ sigaction(SIGUSR1, &sa, NULL);
+}
+
+
static void EnableDebugSignalHandler(int signo) {
// Call only async signal-safe functions here!
v8::Debug::DebugBreak(*static_cast<Isolate* volatile*>(&node_isolate));
static int RegisterDebugSignalHandler() {
// FIXME(bnoordhuis) Should be per-isolate or per-context, not global.
RegisterSignalHandler(SIGUSR1, EnableDebugSignalHandler);
+ // If we caught a SIGUSR1 during the bootstrap process, re-raise it
+ // now that the debugger infrastructure is in place.
+ if (caught_early_debug_signal) raise(SIGUSR1);
return 0;
}
#endif // __POSIX__
int Start(int argc, char** argv) {
+#if !defined(_WIN32)
+ // Try hard not to lose SIGUSR1 signals during the bootstrap process.
+ InstallEarlyDebugSignalHandler();
+#endif
+
assert(argc > 0);
// Hack around with the argv pointer. Used for process.title = "blah".
console.error('got stderr data %j', data);
nodeProcess.stderr.resume();
b += data;
- if (didTryConnect == false &&
- b.match(/Debugger listening on port/)) {
+ if (didTryConnect === false && b.match(/Debugger listening on port/)) {
didTryConnect = true;
- setTimeout(function() {
+ // The timeout is here to expose a race in the bootstrap process.
+ // Without the early SIGUSR1 debug handler, it effectively results
+ // in an infinite ECONNREFUSED loop.
+ setTimeout(tryConnect, 100);
+
+ function tryConnect() {
// Wait for some data before trying to connect
var c = new debug.Client();
console.error('>>> connecting...');
done();
});
});
- });
+ c.on('error', function(err) {
+ if (err.code !== 'ECONNREFUSED') throw err;
+ setTimeout(tryConnect, 10);
+ });
+ }
}
});
}