From 0195310b3572f78ec02a0f4a75378b3cc6009ff7 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 22 Jul 2014 21:20:49 -0400 Subject: [PATCH] fix previous commit for linux, and cleanup some profile behaviors --- base/multi.jl | 2 ++ src/init.c | 10 +++++- src/profile.c | 88 ++++++++++++++++++++++++++++++++------------------- 3 files changed, 66 insertions(+), 34 deletions(-) diff --git a/base/multi.jl b/base/multi.jl index 17a005d71b0c1..9f7deedc63339 100644 --- a/base/multi.jl +++ b/base/multi.jl @@ -908,6 +908,8 @@ function create_message_handler_loop(sock::AsyncStream) #returns immediately end # end of while catch e + display_error(e, catch_backtrace()) + iderr = worker_id_from_socket(sock) # If error occured talking to pid 1, commit harakiri if iderr == 1 diff --git a/src/init.c b/src/init.c index 5bd740f20c735..8dd6c1e6987c6 100644 --- a/src/init.c +++ b/src/init.c @@ -140,6 +140,10 @@ static int is_addr_on_stack(void *addr) #endif } +#ifndef SIGINFO +#define SIGINFO SIGUSR1 +#endif + void sigdie_handler(int sig, siginfo_t *info, void *context) { if (sig != SIGINFO) { sigset_t sset; @@ -876,7 +880,7 @@ void julia_init(char *imageFile) struct sigaction act; memset(&act, 0, sizeof(struct sigaction)); sigemptyset(&act.sa_mask); - act.sa_sigaction = sigdie_handler; + act.sa_sigaction = segv_handler; act.sa_flags = SA_ONSTACK | SA_SIGINFO; if (sigaction(SIGSEGV, &act, NULL) < 0) { JL_PRINTF(JL_STDERR, "sigaction: %s\n", strerror(errno)); @@ -916,6 +920,10 @@ void julia_init(char *imageFile) JL_PRINTF(JL_STDERR, "sigaction: %s\n", strerror(errno)); jl_exit(1); } + if (sigaction(SIGPIPE, &act_die, NULL) < 0) { + JL_PRINTF(JL_STDERR, "sigaction: %s\n", strerror(errno)); + jl_exit(1); + } #else // defined(_OS_WINDOWS_) if (signal(SIGFPE, (void (__cdecl *)(int))fpe_handler) == SIG_ERR) { JL_PRINTF(JL_STDERR, "Couldn't set SIGFPE\n"); diff --git a/src/profile.c b/src/profile.c index 8668d6572662a..deeffcb9d2e59 100644 --- a/src/profile.c +++ b/src/profile.c @@ -16,6 +16,9 @@ static volatile int running = 0; ///////////////////////////////////////// // Timers to take samples at intervals // ///////////////////////////////////////// +DLLEXPORT void jl_profile_stop_timer(void); +DLLEXPORT int jl_profile_start_timer(void); + #if defined(_WIN32) // // Windows @@ -263,8 +266,8 @@ DLLEXPORT int jl_profile_start_timer(void) profile_started = 1; } - timerprof.tv_sec = 0; - timerprof.tv_nsec = nsecprof; + timerprof.tv_sec = nsecprof/1000000; + timerprof.tv_nsec = nsecprof%1000000; running = 1; ret = clock_alarm(clk, TIME_RELATIVE, timerprof, profile_port); @@ -286,38 +289,58 @@ DLLEXPORT void jl_profile_stop_timer(void) struct itimerval timerprof; // The handler function, called whenever the profiling timer elapses -static void profile_bt(int dummy) +static void profile_bt(int sig) { - // Get backtrace data - bt_size_cur += rec_backtrace((ptrint_t*)bt_data_prof+bt_size_cur, bt_size_max-bt_size_cur-1); - // Mark the end of this block with 0 - bt_data_prof[bt_size_cur] = 0; - bt_size_cur++; - // Re-arm the timer if (running && bt_size_cur < bt_size_max) { - timerprof.it_value.tv_usec = nsecprof/1000; - setitimer(ITIMER_REAL, &timerprof, 0); - signal(SIGALRM, profile_bt); + // Get backtrace data + bt_size_cur += rec_backtrace((ptrint_t*)bt_data_prof+bt_size_cur, bt_size_max-bt_size_cur-1); + // Mark the end of this block with 0 + bt_data_prof[bt_size_cur] = 0; + bt_size_cur++; + } + if (bt_size_cur >= bt_size_max) { + // Buffer full: Delete the timer + jl_profile_stop_timer(); } } DLLEXPORT int jl_profile_start_timer(void) { - timerprof.it_interval.tv_sec = 0; - timerprof.it_interval.tv_usec = 0; - timerprof.it_value.tv_sec = 0; - timerprof.it_value.tv_usec = nsecprof/1000; - if (setitimer(ITIMER_REAL, &timerprof, 0) == -1) + struct sigevent sigprof; + struct sigaction sa; + sigset_t ss; + + // Make sure SIGPROF is unblocked + sigemptyset(&ss); + sigaddset(&ss, SIGPROF); + if (sigprocmask(SIG_UNBLOCK, &ss, NULL) == -1) + return -4; + + // Establish the signal handler + memset(&sa, 0, sizeof(struct sigaction)); + sa.sa_handler = profile_bt; + sigemptyset(&sa.sa_mask); + if (sigaction(SIGPROF, &sa, NULL) == -1) + return -1; + + timerprof.it_interval.tv_sec = nsecprof/1000000; + timerprof.it_interval.tv_usec = (nsecprof/1000)%1000; + timerprof.it_value.tv_sec = nsecprof/1000000; + timerprof.it_value.tv_usec = (nsecprof/1000)%1000; + if (setitimer(ITIMER_PROF, &timerprof, 0) == -1) return -3; running = 1; - signal(SIGALRM, profile_bt); return 0; } DLLEXPORT void jl_profile_stop_timer(void) { + if (running) { + memset(&timerprof, 0, sizeof(timerprof)); + setitimer(ITIMER_PROF, &timerprof, 0); + } running = 0; } #else @@ -334,17 +357,16 @@ static struct itimerspec itsprof; // The handler function, called whenever the profiling timer elapses static void profile_bt(int signal, siginfo_t *si, void *uc) { - if (si->si_value.sival_ptr == &timerprof && bt_size_cur < bt_size_max) { + if (running && si->si_value.sival_ptr == &timerprof && bt_size_cur < bt_size_max) { // Get backtrace data bt_size_cur += rec_backtrace((ptrint_t*)bt_data_prof+bt_size_cur, bt_size_max-bt_size_cur-1); // Mark the end of this block with 0 bt_data_prof[bt_size_cur] = 0; bt_size_cur++; - // Re-arm the timer - if (bt_size_cur < bt_size_max) { - itsprof.it_value.tv_nsec = nsecprof; - timer_settime(timerprof, 0, &itsprof, NULL); - } + } + if (bt_size_cur >= bt_size_max) { + // Buffer full: Delete the timer + jl_profile_stop_timer(); } } @@ -354,9 +376,9 @@ DLLEXPORT int jl_profile_start_timer(void) struct sigaction sa; sigset_t ss; - // Make sure SIGUSR1 is unblocked + // Make sure SIGUSR2 is unblocked sigemptyset(&ss); - sigaddset(&ss, SIGUSR1); + sigaddset(&ss, SIGUSR2); if (sigprocmask(SIG_UNBLOCK, &ss, NULL) == -1) return -4; @@ -365,22 +387,22 @@ DLLEXPORT int jl_profile_start_timer(void) sa.sa_flags = SA_SIGINFO; sa.sa_sigaction = profile_bt; sigemptyset(&sa.sa_mask); - if (sigaction(SIGUSR1, &sa, NULL) == -1) + if (sigaction(SIGUSR2, &sa, NULL) == -1) return -1; // Establish the signal event memset(&sigprof, 0, sizeof(struct sigevent)); sigprof.sigev_notify = SIGEV_SIGNAL; - sigprof.sigev_signo = SIGUSR1; + sigprof.sigev_signo = SIGUSR2; sigprof.sigev_value.sival_ptr = &timerprof; - if (timer_create(CLOCK_REALTIME, &sigprof, &timerprof) == -1) + if (timer_create(CLOCK_PROCESS_CPUTIME_ID, &sigprof, &timerprof) == -1) return -2; // Start the timer - itsprof.it_value.tv_sec = 0; - itsprof.it_interval.tv_sec = 0; // make it fire once - itsprof.it_interval.tv_nsec = 0; - itsprof.it_value.tv_nsec = nsecprof; + itsprof.it_interval.tv_sec = nsecprof/1000000; + itsprof.it_interval.tv_nsec = nsecprof%1000000; + itsprof.it_value.tv_sec = nsecprof/1000000; + itsprof.it_value.tv_nsec = nsecprof%1000000; if (timer_settime(timerprof, 0, &itsprof, NULL) == -1) return -3;