Skip to content

Commit

Permalink
Merge pull request #18354 from JuliaLang/yyc/signals/dbg
Browse files Browse the repository at this point in the history
Make `Ctrl-C` in the debugger works again.
  • Loading branch information
yuyichao committed Sep 6, 2016
2 parents 22cc7a5 + a1d6300 commit 8761c48
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 13 deletions.
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

0 comments on commit 8761c48

Please sign in to comment.