Skip to content

Commit

Permalink
Merge pull request JuliaLang#11517 from JuliaLang/kf/segvexc
Browse files Browse the repository at this point in the history
Add an option to turn segfaults into julia errors
  • Loading branch information
Keno committed Jun 1, 2015
2 parents 25923b1 + ccab029 commit 3c853e2
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 1 deletion.
3 changes: 2 additions & 1 deletion base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ export
# errors
BoundsError, DivideError, DomainError, Exception,
InexactError, InterruptException, OutOfMemoryError, OverflowError,
StackOverflowError, UndefRefError, UndefVarError,
StackOverflowError, SegmentationFault, UndefRefError, UndefVarError,
# AST representation
Expr, GotoNode, LabelNode, LineNumberNode, QuoteNode, SymbolNode, TopNode,
GlobalRef, NewvarNode, GenSym,
Expand Down Expand Up @@ -218,6 +218,7 @@ immutable DomainError <: Exception end
immutable OverflowError <: Exception end
immutable InexactError <: Exception end
immutable OutOfMemoryError <: Exception end
immutable SegmentationFault <: Exception end
immutable StackOverflowError <: Exception end
immutable UndefRefError <: Exception end
immutable UndefVarError <: Exception
Expand Down
1 change: 1 addition & 0 deletions base/essentials.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ call(T::Type{OverflowError}) = Core.call(T)
call(T::Type{InexactError}) = Core.call(T)
call(T::Type{OutOfMemoryError}) = Core.call(T)
call(T::Type{StackOverflowError}) = Core.call(T)
call(T::Type{SegmentationFault}) = Core.call(T)
call(T::Type{UndefRefError}) = Core.call(T)
call(T::Type{UndefVarError}, var::Symbol) = Core.call(T, var)
call(T::Type{InterruptException}) = Core.call(T)
Expand Down
3 changes: 3 additions & 0 deletions src/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ jl_datatype_t *jl_void_type;
jl_datatype_t *jl_voidpointer_type;
jl_value_t *jl_an_empty_cell=NULL;
jl_value_t *jl_stackovf_exception;
#ifdef SEGV_EXCEPTION
jl_value_t *jl_segv_exception;
#endif
jl_value_t *jl_diverror_exception;
jl_value_t *jl_domain_exception;
jl_value_t *jl_overflow_exception;
Expand Down
32 changes: 32 additions & 0 deletions src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,9 +290,18 @@ void segv_handler(int sig, siginfo_t *info, void *context)
sigprocmask(SIG_UNBLOCK, &sset, NULL);
jl_throw(jl_memory_exception);
}
#ifdef SEGV_EXCEPTION
else {
sigemptyset(&sset);
sigaddset(&sset, SIGSEGV);
sigprocmask(SIG_UNBLOCK, &sset, NULL);
jl_throw(jl_segv_exception);
}
#else
else {
sigdie_handler(sig, info, context);
}
#endif
}
#endif

Expand Down Expand Up @@ -747,6 +756,17 @@ void *mach_segv_listener(void *arg)
}
}

#ifdef SEGV_EXCEPTION

void darwin_segv_handler(unw_context_t *uc)
{
bt_size = rec_backtrace_ctx(bt_data, MAX_BT_SIZE, uc);
jl_exception_in_transit = jl_segv_exception;
jl_rethrow();
}

#endif

void darwin_stack_overflow_handler(unw_context_t *uc)
{
bt_size = rec_backtrace_ctx(bt_data, MAX_BT_SIZE, uc);
Expand Down Expand Up @@ -799,8 +819,12 @@ kern_return_t catch_exception_raise(mach_port_t exception_port,
ret = thread_get_state(thread,x86_EXCEPTION_STATE64,(thread_state_t)&exc_state,&exc_count);
HANDLE_MACH_ERROR("thread_get_state(1)",ret);
uint64_t fault_addr = exc_state.__faultvaddr;
#ifdef SEGV_EXCEPTION
if (1) {
#else
if (is_addr_on_stack((void*)fault_addr) ||
((exc_state.__err & PAGE_PRESENT) == PAGE_PRESENT)) {
#endif
ret = thread_get_state(thread,x86_THREAD_STATE64,(thread_state_t)&state,&count);
HANDLE_MACH_ERROR("thread_get_state(2)",ret);
old_state = state;
Expand All @@ -823,6 +847,10 @@ kern_return_t catch_exception_raise(mach_port_t exception_port,
state.__rdi = (uint64_t)uc;
if ((exc_state.__err & PAGE_PRESENT) == PAGE_PRESENT)
state.__rip = (uint64_t)darwin_accerr_handler;
#ifdef SEGV_EXCEPTION
else if (!is_addr_on_stack((void*)fault_addr))
state.__rip = (uint64_t)darwin_segv_handler;
#endif
else
state.__rip = (uint64_t)darwin_stack_overflow_handler;

Expand Down Expand Up @@ -1341,6 +1369,10 @@ void jl_get_builtin_hooks(void)
jl_boundserror_type = (jl_datatype_t*)core("BoundsError");
jl_memory_exception = jl_new_struct_uninit((jl_datatype_t*)core("OutOfMemoryError"));

#ifdef SEGV_EXCEPTION
jl_segv_exception = jl_new_struct_uninit((jl_datatype_t*)core("SegmentationFault"));
#endif

jl_ascii_string_type = (jl_datatype_t*)core("ASCIIString");
jl_utf8_string_type = (jl_datatype_t*)core("UTF8String");
jl_symbolnode_type = (jl_datatype_t*)core("SymbolNode");
Expand Down
4 changes: 4 additions & 0 deletions src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,10 @@ DLLEXPORT void jl_atexit_hook();
#define HAVE_CPUID
#endif

#ifdef SEGV_EXCEPTION
extern DLLEXPORT jl_value_t *jl_segv_exception;
#endif

#ifdef __cplusplus
}
#endif
Expand Down
5 changes: 5 additions & 0 deletions src/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@
// reachable memory is freed
//#define GC_VERIFY

// SEGV_EXCEPTION turns segmentation faults into catchable julia exceptions.
// This is not recommended, as the memory state after such an exception should
// be considered untrusted, but can be helpful during development
// #define SEGV_EXCEPTION

// profiling options

// GC_FINAL_STATS prints total GC stats at exit
Expand Down

0 comments on commit 3c853e2

Please sign in to comment.