Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

src: rework early debug signal handling #615

Merged
merged 3 commits into from
Jan 28, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 55 additions & 54 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3096,22 +3096,6 @@ static void DispatchDebugMessagesAsyncCallback(uv_async_t* handle) {


#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, nullptr);
}


static void EnableDebugSignalHandler(int signo) {
// Call only async signal-safe functions here!
v8::Debug::DebugBreak(*static_cast<Isolate* volatile*>(&node_isolate));
Expand Down Expand Up @@ -3152,10 +3136,11 @@ void DebugProcess(const FunctionCallbackInfo<Value>& args) {
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);
// Unblock SIGUSR1. A pending SIGUSR1 signal will now be delivered.
sigset_t sigmask;
sigemptyset(&sigmask);
sigaddset(&sigmask, SIGUSR1);
CHECK_EQ(0, pthread_sigmask(SIG_UNBLOCK, &sigmask, nullptr));
return 0;
}
#endif // __POSIX__
Expand Down Expand Up @@ -3322,6 +3307,54 @@ static void DebugEnd(const FunctionCallbackInfo<Value>& args) {
}


inline void PlatformInit() {
#ifdef __POSIX__
sigset_t sigmask;
sigemptyset(&sigmask);
sigaddset(&sigmask, SIGUSR1);
CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &sigmask, nullptr));

// Restore signal dispositions, the parent process may have changed them.
struct sigaction act;
memset(&act, 0, sizeof(act));

// The hard-coded upper limit is because NSIG is not very reliable; on Linux,
// it evaluates to 32, 34 or 64, depending on whether RT signals are enabled.
// Counting up to SIGRTMIN doesn't work for the same reason.
for (unsigned nr = 1; nr < 32; nr += 1) {
if (nr == SIGKILL || nr == SIGSTOP)
continue;
act.sa_handler = (nr == SIGPIPE) ? SIG_IGN : SIG_DFL;
CHECK_EQ(0, sigaction(nr, &act, nullptr));
}

RegisterSignalHandler(SIGINT, SignalExit, true);
RegisterSignalHandler(SIGTERM, SignalExit, true);

// Raise the open file descriptor limit.
struct rlimit lim;
if (getrlimit(RLIMIT_NOFILE, &lim) == 0 && lim.rlim_cur != lim.rlim_max) {
// Do a binary search for the limit.
rlim_t min = lim.rlim_cur;
rlim_t max = 1 << 20;
// But if there's a defined upper bound, don't search, just set it.
if (lim.rlim_max != RLIM_INFINITY) {
min = lim.rlim_max;
max = lim.rlim_max;
}
do {
lim.rlim_cur = min + (max - min) / 2;
if (setrlimit(RLIMIT_NOFILE, &lim)) {
max = lim.rlim_cur;
} else {
min = lim.rlim_cur;
}
} while (min + 1 < max);
}
#endif // __POSIX__
}


void Init(int* argc,
const char** argv,
int* exec_argc,
Expand Down Expand Up @@ -3396,35 +3429,6 @@ void Init(int* argc,

V8::SetArrayBufferAllocator(&ArrayBufferAllocator::the_singleton);

#ifdef __POSIX__
// Raise the open file descriptor limit.
{ // NOLINT (whitespace/braces)
struct rlimit lim;
if (getrlimit(RLIMIT_NOFILE, &lim) == 0 && lim.rlim_cur != lim.rlim_max) {
// Do a binary search for the limit.
rlim_t min = lim.rlim_cur;
rlim_t max = 1 << 20;
// But if there's a defined upper bound, don't search, just set it.
if (lim.rlim_max != RLIM_INFINITY) {
min = lim.rlim_max;
max = lim.rlim_max;
}
do {
lim.rlim_cur = min + (max - min) / 2;
if (setrlimit(RLIMIT_NOFILE, &lim)) {
max = lim.rlim_cur;
} else {
min = lim.rlim_cur;
}
} while (min + 1 < max);
}
}
// Ignore SIGPIPE
RegisterSignalHandler(SIGPIPE, SIG_IGN);
RegisterSignalHandler(SIGINT, SignalExit, true);
RegisterSignalHandler(SIGTERM, SignalExit, true);
#endif // __POSIX__

if (!use_debug_agent) {
RegisterDebugSignalHandler();
}
Expand Down Expand Up @@ -3610,16 +3614,13 @@ Environment* CreateEnvironment(Isolate* isolate,


int Start(int argc, char** argv) {
PlatformInit();

const char* replaceInvalid = secure_getenv("NODE_INVALID_UTF8");

if (replaceInvalid == nullptr)
WRITE_UTF8_FLAGS |= String::REPLACE_INVALID_UTF8;

#if !defined(_WIN32)
// Try hard not to lose SIGUSR1 signals during the bootstrap process.
InstallEarlyDebugSignalHandler();
#endif

CHECK_GT(argc, 0);

// Hack around with the argv pointer. Used for process.title = "blah".
Expand Down