Skip to content

Commit

Permalink
fix previous commit for linux, and cleanup some profile behaviors
Browse files Browse the repository at this point in the history
  • Loading branch information
vtjnash committed Jul 24, 2014
1 parent 0fbf135 commit 0195310
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 34 deletions.
2 changes: 2 additions & 0 deletions base/multi.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 9 additions & 1 deletion src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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");
Expand Down
88 changes: 55 additions & 33 deletions src/profile.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand All @@ -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();
}
}

Expand All @@ -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;

Expand All @@ -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)

This comment has been minimized.

Copy link
@timholy

timholy Jul 28, 2014

Member

Now that I've looked at this more deeply (see 0daeb41), I am also concerned about switching from walltime to cputime. Matlab uses CPU time as their default, and it's quite misleading when you profile multithreaded functions---a multithreaded implementation like bsxfun can appear to be slower than the abysmal repmat. Not sure if it will have the same impact here, however.

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;

Expand Down

1 comment on commit 0195310

@JeffBezanson
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another cautionary tale of combining unrelated changes in the same commit. Should not have changed both the signaling and which clock is used.

Please sign in to comment.