Skip to content

Commit

Permalink
--safe-crash-log-file flag
Browse files Browse the repository at this point in the history
  • Loading branch information
d-netto committed Mar 22, 2024
1 parent 31f3d1d commit fceefbd
Show file tree
Hide file tree
Showing 9 changed files with 59 additions and 13 deletions.
1 change: 1 addition & 0 deletions base/options.jl
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ struct JLOptions
strip_ir::Int8
permalloc_pkgimg::Int8
heap_size_hint::UInt64
safe_crash_log_file::Ptr{UInt8}
end

# This runs early in the sysimage != is not defined yet
Expand Down
9 changes: 9 additions & 0 deletions src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,15 @@ JL_DLLEXPORT void julia_init(JL_IMAGE_SEARCH rel)
if (jl_options.handle_signals == JL_OPTIONS_HANDLE_SIGNALS_ON)
jl_install_default_signal_handlers();

#if defined(_OS_LINUX_) && defined(_CPU_X86_64_)
if (jl_options.safe_crash_log_file != NULL) {
jl_sig_fd = open(jl_options.safe_crash_log_file, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (jl_sig_fd == -1) {
jl_error("fatal error: could not open safe crash log file for writing");
}
}
#endif

jl_gc_init();

arraylist_new(&jl_linkage_blobs, 0);
Expand Down
11 changes: 9 additions & 2 deletions src/jl_uv.c
Original file line number Diff line number Diff line change
Expand Up @@ -693,8 +693,15 @@ JL_DLLEXPORT void jl_safe_printf(const char *fmt, ...)
va_end(args);

buf[999] = '\0';
if (write(STDERR_FILENO, buf, strlen(buf)) < 0) {
// nothing we can do; ignore the failure
if (jl_inside_signal_handler() && jl_sig_fd != 0) {
if (write(jl_sig_fd, buf, strlen(buf)) < 0) {
// nothing we can do; ignore the failure
}
}
else {
if (write(STDERR_FILENO, buf, strlen(buf)) < 0) {
// nothing we can do; ignore the failure
}
}
#ifdef _OS_WINDOWS_
SetLastError(last_error);
Expand Down
10 changes: 9 additions & 1 deletion src/jloptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ JL_DLLEXPORT void jl_init_options(void)
0, // strip-ir
0, // permalloc_pkgimg
0, // heap-size-hint
NULL, // safe_crash_log_file
};
jl_options_initialized = 1;
}
Expand Down Expand Up @@ -258,7 +259,8 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp)
opt_strip_ir,
opt_heap_size_hint,
opt_gc_threads,
opt_permalloc_pkgimg
opt_permalloc_pkgimg,
opt_safe_crash_log_file,
};
static const char* const shortopts = "+vhqH:e:E:L:J:C:it:p:O:g:";
static const struct option longopts[] = {
Expand Down Expand Up @@ -320,6 +322,7 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp)
{ "strip-ir", no_argument, 0, opt_strip_ir },
{ "permalloc-pkgimg",required_argument, 0, opt_permalloc_pkgimg },
{ "heap-size-hint", required_argument, 0, opt_heap_size_hint },
{ "safe-crash-log-file", required_argument, 0, opt_safe_crash_log_file },
{ 0, 0, 0, 0 }
};

Expand Down Expand Up @@ -850,6 +853,11 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp)
else
jl_errorf("julia: invalid argument to --permalloc-pkgimg={yes|no} (%s)", optarg);
break;
case opt_safe_crash_log_file:
jl_options.safe_crash_log_file = strdup(optarg);
if (jl_options.safe_crash_log_file == NULL)
jl_error("julia: failed to allocate memory for --safe-crash-log-file");
break;
default:
jl_errorf("julia: unhandled option -- %c\n"
"This is a bug, please report it.", c);
Expand Down
1 change: 1 addition & 0 deletions src/jloptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ typedef struct {
int8_t strip_ir;
int8_t permalloc_pkgimg;
uint64_t heap_size_hint;
const char *safe_crash_log_file;
} jl_options_t;

#endif
23 changes: 23 additions & 0 deletions src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,29 @@ JL_CALLABLE(jl_f_opaque_closure_call);
void jl_install_default_signal_handlers(void);
void restore_signals(void);
void jl_install_thread_signal_handler(jl_ptls_t ptls);
extern void *signal_stack;
extern size_t sig_stack_size;
STATIC_INLINE int is_addr_on_sigstack(jl_ptls_t ptls, void *ptr)
{
// One guard page for signal_stack.
return !((char*)ptr < (char*)ptls->signal_stack - jl_page_size ||
(char*)ptr > (char*)ptls->signal_stack + sig_stack_size);
}
STATIC_INLINE int jl_inside_signal_handler(void)
{
#if defined(_OS_LINUX_) && defined(_CPU_X86_64_)
// Read the stack pointer
size_t sp;
__asm__ __volatile__("movq %%rsp, %0" : "=r"(sp));
// Check if the stack pointer is within the signal stack
jl_ptls_t ptls = jl_current_task->ptls;
return is_addr_on_sigstack(ptls, (void*)sp);
#else
return 0;
#endif
}
// File-descriptor for safe logging on signal handling
extern int jl_sig_fd;

JL_DLLEXPORT jl_fptr_args_t jl_get_builtin_fptr(jl_value_t *b);

Expand Down
4 changes: 4 additions & 0 deletions src/signal-handling.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ static const uint64_t GIGA = 1000000000ULL;
// Timers to take samples at intervals
JL_DLLEXPORT void jl_profile_stop_timer(void);
JL_DLLEXPORT int jl_profile_start_timer(void);
// Signal stack
void *signal_stack = NULL;
// File-descriptor for safe logging on signal handling
int jl_sig_fd;

///////////////////////
// Utility functions //
Expand Down
11 changes: 2 additions & 9 deletions src/signals-unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
// 8M signal stack, same as default stack size and enough
// for reasonable finalizers.
// Should also be enough for parallel GC when we have it =)
#define sig_stack_size (8 * 1024 * 1024)
size_t sig_stack_size = (8 * 1024 * 1024);

#include "julia_assert.h"

Expand Down Expand Up @@ -91,13 +91,6 @@ static inline __attribute__((unused)) uintptr_t jl_get_rsp_from_ctx(const void *
#endif
}

static int is_addr_on_sigstack(jl_ptls_t ptls, void *ptr)
{
// One guard page for signal_stack.
return !((char*)ptr < (char*)ptls->signal_stack - jl_page_size ||
(char*)ptr > (char*)ptls->signal_stack + sig_stack_size);
}

// Modify signal context `_ctx` so that `fptr` will execute when the signal
// returns. `fptr` will execute on the signal stack, and must not return.
// jl_call_in_ctx is also currently executing on that signal stack,
Expand Down Expand Up @@ -640,7 +633,7 @@ static void *alloc_sigstack(size_t *ssize)
void jl_install_thread_signal_handler(jl_ptls_t ptls)
{
size_t ssize = sig_stack_size;
void *signal_stack = alloc_sigstack(&ssize);
signal_stack = alloc_sigstack(&ssize);
ptls->signal_stack = signal_stack;
stack_t ss;
ss.ss_flags = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/signals-win.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// Note that this file is `#include`d by "signal-handling.c"
#include <mmsystem.h> // hidden by LEAN_AND_MEAN

#define sig_stack_size 131072 // 128k reserved for SEGV handling
size_t sig_stack_size = 131072; // 128k reserved for SEGV handling

// Copied from MINGW_FLOAT_H which may not be found due to a collision with the builtin gcc float.h
// eventually we can probably integrate this into OpenLibm.
Expand Down

0 comments on commit fceefbd

Please sign in to comment.