From ed41f7c398fa7a80642658e6b947904ece07059e Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Thu, 17 Feb 2022 12:52:29 -0500 Subject: [PATCH] Profile: Minor fixes. Signal handling fix. (#44199) (cherry picked from commit 072c041f8fe19a3c94dc4a249de975c64a004d62) --- src/signal-handling.c | 11 ++++++----- src/signals-unix.c | 20 +++++++++++++++----- stdlib/Profile/Project.toml | 3 ++- stdlib/Profile/src/Profile.jl | 5 +++-- stdlib/Profile/test/runtests.jl | 2 -- 5 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/signal-handling.c b/src/signal-handling.c index 142f03b6c899d..d9c53b0211eae 100644 --- a/src/signal-handling.c +++ b/src/signal-handling.c @@ -132,22 +132,23 @@ static size_t jl_safe_read_mem(const volatile char *ptr, char *out, size_t len) static double profile_autostop_time = -1.0; static double profile_peek_duration = 1.0; // seconds -double jl_get_profile_peek_duration(void) { +double jl_get_profile_peek_duration(void) +{ return profile_peek_duration; } -void jl_set_profile_peek_duration(double t) { +void jl_set_profile_peek_duration(double t) +{ profile_peek_duration = t; - return; } uintptr_t profile_show_peek_cond_loc; JL_DLLEXPORT void jl_set_peek_cond(uintptr_t cond) { profile_show_peek_cond_loc = cond; - return; } -static void jl_check_profile_autostop(void) { +static void jl_check_profile_autostop(void) +{ if ((profile_autostop_time != -1.0) && (jl_hrtime() > profile_autostop_time)) { profile_autostop_time = -1.0; jl_profile_stop_timer(); diff --git a/src/signals-unix.c b/src/signals-unix.c index b2e3ef2952029..8a5822d451335 100644 --- a/src/signals-unix.c +++ b/src/signals-unix.c @@ -539,9 +539,13 @@ JL_DLLEXPORT int jl_profile_start_timer(void) JL_DLLEXPORT void jl_profile_stop_timer(void) { - if (running) + if (running) { timer_delete(timerprof); - running = 0; + // 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); + running = 0; + } } #elif defined(HAVE_ITIMER) @@ -556,18 +560,24 @@ JL_DLLEXPORT int jl_profile_start_timer(void) timerprof.it_interval.tv_usec = 0; timerprof.it_value.tv_sec = nsecprof / GIGA; timerprof.it_value.tv_usec = ((nsecprof % GIGA) + 999) / 1000; - if (setitimer(ITIMER_PROF, &timerprof, NULL) == -1) - return -3; + // Because SIGUSR1 is multipurpose, set `running` before so that we know that the first SIGUSR1 came from the timer running = 1; + if (setitimer(ITIMER_PROF, &timerprof, NULL) == -1) { + running = 0; + return -3; + } return 0; } JL_DLLEXPORT void jl_profile_stop_timer(void) { if (running) { - running = 0; 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); + running = 0; } } diff --git a/stdlib/Profile/Project.toml b/stdlib/Profile/Project.toml index 1d13dad22233a..334d475832b6d 100644 --- a/stdlib/Profile/Project.toml +++ b/stdlib/Profile/Project.toml @@ -5,9 +5,10 @@ uuid = "9abbd945-dff8-562f-b5e8-e1ebf5ef1b79" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" [extras] +Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["Logging", "Serialization", "Test"] +test = ["Base64", "Logging", "Serialization", "Test"] diff --git a/stdlib/Profile/src/Profile.jl b/stdlib/Profile/src/Profile.jl index 50e03d2c79a5a..b11dfb488c373 100644 --- a/stdlib/Profile/src/Profile.jl +++ b/stdlib/Profile/src/Profile.jl @@ -54,7 +54,7 @@ function _peek_report() iob = IOBuffer() ioc = IOContext(IOContext(iob, stdout), :displaysize=>displaysize(stdout)) print(ioc, groupby = [:thread, :task]) - Base.print(stdout, String(resize!(iob.data, iob.size))) + Base.print(stdout, String(take!(iob))) end # This is a ref so that it can be overridden by other profile info consumers. const peek_report = Ref{Function}(_peek_report) @@ -73,7 +73,8 @@ Set the duration in seconds of the profile "peek" that is triggered via `SIGINFO set_peek_duration(t::Float64) = ccall(:jl_set_profile_peek_duration, Cvoid, (Float64,), t) precompile_script = """ -Profile.@profile sleep(0.5) +import Profile +Profile.@profile while Profile.len_data() < 1000; rand(10,10) * rand(10,10); end Profile.peek_report[]() Profile.clear() """ diff --git a/stdlib/Profile/test/runtests.jl b/stdlib/Profile/test/runtests.jl index 50917b9797c7d..ab87d497fe93e 100644 --- a/stdlib/Profile/test/runtests.jl +++ b/stdlib/Profile/test/runtests.jl @@ -226,8 +226,6 @@ if Sys.isbsd() || Sys.islinux() end end end -else - @warn "Skipping \"SIGINFO/SIGUSR1 profile triggering\" test as it is not supported on this platform" end @testset "FlameGraphs" begin