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

Make Ctrl-C in the debugger works again. #18354

Merged
merged 1 commit into from
Sep 6, 2016
Merged
Show file tree
Hide file tree
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
28 changes: 24 additions & 4 deletions src/signal-handling.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,32 @@ static int jl_check_force_sigint(void)
return 0;
}

// Force sigint requires pressing `Ctrl-C` repeatedly.
// Ignore sigint for a short time after that to avoid rethrowing sigint too
// quickly again. (Code that has this issue is inherently racy but this is
// an interactive feature anyway.)
#ifndef _OS_WINDOWS_
// Not thread local, should only be accessed by the signal handler thread.
static volatile int jl_sigint_passed = 0;
static sigset_t jl_sigint_sset;
#endif

static int jl_ignore_sigint(void)
{
// On Unix, we get the SIGINT before the debugger which makes it very
// hard to interrupt a running process in the debugger with `Ctrl-C`.
// Manually raise a `SIGINT` on current thread with the signal temporarily
// unblocked and use it's behavior to decide if we need to handle the signal.
#ifndef _OS_WINDOWS_
jl_sigint_passed = 0;
pthread_sigmask(SIG_UNBLOCK, &jl_sigint_sset, NULL);
// This can swallow an external `SIGINT` but it's not an issue
// since we don't deliver the same number of signals anyway.
pthread_kill(pthread_self(), SIGINT);
pthread_sigmask(SIG_BLOCK, &jl_sigint_sset, NULL);
if (!jl_sigint_passed)
return 1;
#endif
// Force sigint requires pressing `Ctrl-C` repeatedly.
// Ignore sigint for a short time after that to avoid rethrowing sigint too
// quickly again. (Code that has this issue is inherently racy but this is
// an interactive feature anyway.)
return jl_disable_sigint_time && jl_disable_sigint_time > uv_hrtime();
}

Expand Down
24 changes: 21 additions & 3 deletions src/signals-unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -519,12 +519,14 @@ static void *signal_listener(void *arg)
# endif
#endif
if (sig == SIGINT) {
if (exit_on_sigint) {
if (jl_ignore_sigint()) {
continue;
}
else if (exit_on_sigint) {
critical = 1;
}
else {
if (!jl_ignore_sigint())
jl_try_deliver_sigint();
jl_try_deliver_sigint();
continue;
}
}
Expand Down Expand Up @@ -600,6 +602,9 @@ static void *signal_listener(void *arg)

void restore_signals(void)
{
sigemptyset(&jl_sigint_sset);
sigaddset(&jl_sigint_sset, SIGINT);

sigset_t sset;
jl_sigsetset(&sset);
sigprocmask(SIG_SETMASK, &sset, 0);
Expand All @@ -625,6 +630,11 @@ void fpe_handler(int sig, siginfo_t *info, void *context)
jl_throw_in_ctx(ptls, jl_diverror_exception, context);
}

void sigint_handler(int sig)
{
jl_sigint_passed = 1;
}

void jl_install_default_signal_handlers(void)
{
struct sigaction actf;
Expand All @@ -635,6 +645,14 @@ void jl_install_default_signal_handlers(void)
if (sigaction(SIGFPE, &actf, NULL) < 0) {
jl_errorf("fatal error: sigaction: %s", strerror(errno));
}
struct sigaction actint;
memset(&actint, 0, sizeof(struct sigaction));
sigemptyset(&actint.sa_mask);
actint.sa_handler = sigint_handler;
actint.sa_flags = 0;
if (sigaction(SIGINT, &actint, NULL) < 0) {
jl_errorf("fatal error: sigaction: %s", strerror(errno));
}
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
jl_error("fatal error: Couldn't set SIGPIPE");
}
Expand Down
14 changes: 8 additions & 6 deletions src/signals-win.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,11 @@ void __cdecl crt_sig_handler(int sig, int num)
break;
case SIGINT:
signal(SIGINT, (void (__cdecl *)(int))crt_sig_handler);
if (exit_on_sigint)
jl_exit(130); // 128 + SIGINT
if (!jl_ignore_sigint())
if (!jl_ignore_sigint()) {
if (exit_on_sigint)
jl_exit(130); // 128 + SIGINT
jl_try_throw_sigint();
}
break;
default: // SIGSEGV, (SSIGTERM, IGILL)
memset(&Context, 0, sizeof(Context));
Expand Down Expand Up @@ -179,10 +180,11 @@ static BOOL WINAPI sigint_handler(DWORD wsig) //This needs winapi types to guara
// etc.
default: sig = SIGTERM; break;
}
if (exit_on_sigint)
jl_exit(128 + sig); // 128 + SIGINT
if (!jl_ignore_sigint())
if (!jl_ignore_sigint()) {
if (exit_on_sigint)
jl_exit(128 + sig); // 128 + SIGINT
jl_try_deliver_sigint();
}
return 1;
}

Expand Down