diff --git a/src/signals-unix.c b/src/signals-unix.c index 8a5822d4513356..b4eb57a5501cbf 100644 --- a/src/signals-unix.c +++ b/src/signals-unix.c @@ -501,6 +501,16 @@ void usr2_handler(int sig, siginfo_t *info, void *ctx) errno = errno_save; } +// Because SIGUSR1 is dual-purpose, and the timer can have trailing signals after being deleted, +// a 2-second grace period is imposed to ignore any trailing timer-created signals so they don't get +// confused for user triggers +uint64_t last_timer_delete_time = 0; + +int timer_graceperiod_elapsed(void) +{ + return jl_hrtime() > (last_timer_delete_time + 2e9); +} + #if defined(HAVE_TIMER) // Linux-style #include @@ -541,9 +551,7 @@ JL_DLLEXPORT void jl_profile_stop_timer(void) { if (running) { timer_delete(timerprof); - // Because SIGUSR1 is multipurpose, care must be taken for running = 0 to be set after the timer has fully stopped. - // There may be a pending signal emitted from the timer so wait a few timer cycles - sleep_ms((nsecprof / GIGA) * 1000 * 3); + last_timer_delete_time = jl_hrtime(); running = 0; } } @@ -574,9 +582,7 @@ JL_DLLEXPORT void jl_profile_stop_timer(void) if (running) { memset(&timerprof, 0, sizeof(timerprof)); setitimer(ITIMER_PROF, &timerprof, NULL); - // Because SIGUSR1 is multipurpose, care must be taken for running = 0 to be set after the timer has fully stopped. - // There may be a pending signal emitted from the timer so wait a few timer cycles - sleep_ms((nsecprof / GIGA) * 1000 * 3); + last_timer_delete_time = jl_hrtime(); running = 0; } } @@ -786,7 +792,7 @@ static void *signal_listener(void *arg) } #else if (sig == SIGUSR1) { - if (running != 1) + if (running != 1 && timer_graceperiod_elapsed()) trigger_profile_peek(); doexit = 0; } diff --git a/stdlib/Profile/test/runtests.jl b/stdlib/Profile/test/runtests.jl index ab87d497fe93ec..c6f78cbed05226 100644 --- a/stdlib/Profile/test/runtests.jl +++ b/stdlib/Profile/test/runtests.jl @@ -200,9 +200,12 @@ if Sys.isbsd() || Sys.islinux() """ iob = Base.BufferStream() p = run(pipeline(`$cmd -e $script`, stderr = devnull, stdout = iob), wait = false) - t = Timer(60) do t # should be done in under 10 seconds + t = Timer(120) do t + # should be under 10 seconds, so give it 2 minutes then report failure + println("KILLING BY PROFILE TEST WATCHDOG\n") + kill(p, Base.SIGTERM) + sleep(10) kill(p, Base.SIGKILL) - sleep(5) close(iob) end try @@ -210,7 +213,7 @@ if Sys.isbsd() || Sys.islinux() @assert occursin("started", s) @assert process_running(p) for _ in 1:2 - sleep(2) + sleep(2.5) if Sys.isbsd() kill(p, 29) # SIGINFO elseif Sys.islinux()