Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions base/options.jl
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ struct JLOptions
timeout_for_safepoint_straggler_s::Int16
gc_sweep_always_full::Int8
compress_sysimage::Int8
alert_on_critical_error::Int8
end

# This runs early in the sysimage != is not defined yet
Expand Down
1 change: 1 addition & 0 deletions src/jloptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ JL_DLLEXPORT void jl_init_options(void)
-1, // timeout_for_safepoint_straggler_s
0, // gc_sweep_always_full
0, // compress_sysimage
0, // alert_on_critical_error
};
jl_options_initialized = 1;
}
Expand Down
1 change: 1 addition & 0 deletions src/jloptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ typedef struct {
int16_t timeout_for_safepoint_straggler_s;
int8_t gc_sweep_always_full;
int8_t compress_sysimage;
int8_t alert_on_critical_error;
} jl_options_t;

#endif
114 changes: 85 additions & 29 deletions src/signals-win.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,33 @@ void __cdecl crt_sig_handler(int sig, int num)
}
memset(&Context, 0, sizeof(Context));
RtlCaptureContext(&Context);

ios_t s;
ios_mem(&s, 0);
if (sig == SIGILL)
jl_fprint_sigill(ios_safe_stderr, &Context);
jl_fprint_critical_error(ios_safe_stderr, sig, 0, &Context, jl_get_current_task());
jl_fprint_sigill(&s, &Context);
jl_fprint_critical_error(&s, sig, 0, &Context, jl_get_current_task());

// First write to stderr
ios_write_direct(ios_safe_stderr, &s);

// Then write to Application log
HANDLE event_source = RegisterEventSourceW(NULL, L"julia");
if (event_source != INVALID_HANDLE_VALUE) {
ios_putc('\0', &s);
const wchar_t *strings[] = { ios_utf8_to_wchar(s.buf) };
ReportEventW(
event_source, EVENTLOG_ERROR_TYPE, /* category */ 0, /* event_id */ (DWORD)0xE0000000L,
/* user_sid */ NULL, /* n_strings */ 1, /* data_size */ 0, strings, /* data */ NULL
);
free(strings[0]);

if (jl_options.alert_on_critical_error) {
MessageBoxW(NULL, /* message */ L"error: libjulia received a fatal signal.\n\n"
L"See Application log in Event Viewer for more information.",
/* title */ L"fatal error in libjulia", MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL);
}
}
raise(sig);
}
}
Expand Down Expand Up @@ -283,59 +307,91 @@ LONG WINAPI jl_exception_handler(struct _EXCEPTION_POINTERS *ExceptionInfo)
break;
}
}
ios_t full_error, summary;
ios_mem(&full_error, 0);
if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION) {
jl_safe_printf("\n");
jl_fprint_sigill(ios_safe_stderr, ExceptionInfo->ContextRecord);
jl_safe_fprintf(&full_error, "\n");
jl_fprint_sigill(&full_error, ExceptionInfo->ContextRecord);
}
jl_safe_printf("\nPlease submit a bug report with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.\nException: ");
jl_safe_fprintf(&full_error, "\nPlease submit a bug report with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.\n");
ios_mem(&summary, 128);
jl_safe_fprintf(&summary, "Exception: ");
switch (ExceptionInfo->ExceptionRecord->ExceptionCode) {
case EXCEPTION_ACCESS_VIOLATION:
jl_safe_printf("EXCEPTION_ACCESS_VIOLATION"); break;
jl_safe_fprintf(&summary, "EXCEPTION_ACCESS_VIOLATION"); break;
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
jl_safe_printf("EXCEPTION_ARRAY_BOUNDS_EXCEEDED"); break;
jl_safe_fprintf(&summary, "EXCEPTION_ARRAY_BOUNDS_EXCEEDED"); break;
case EXCEPTION_BREAKPOINT:
jl_safe_printf("EXCEPTION_BREAKPOINT"); break;
jl_safe_fprintf(&summary, "EXCEPTION_BREAKPOINT"); break;
case EXCEPTION_DATATYPE_MISALIGNMENT:
jl_safe_printf("EXCEPTION_DATATYPE_MISALIGNMENT"); break;
jl_safe_fprintf(&summary, "EXCEPTION_DATATYPE_MISALIGNMENT"); break;
case EXCEPTION_FLT_DENORMAL_OPERAND:
jl_safe_printf("EXCEPTION_FLT_DENORMAL_OPERAND"); break;
jl_safe_fprintf(&summary, "EXCEPTION_FLT_DENORMAL_OPERAND"); break;
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
jl_safe_printf("EXCEPTION_FLT_DIVIDE_BY_ZERO"); break;
jl_safe_fprintf(&summary, "EXCEPTION_FLT_DIVIDE_BY_ZERO"); break;
case EXCEPTION_FLT_INEXACT_RESULT:
jl_safe_printf("EXCEPTION_FLT_INEXACT_RESULT"); break;
jl_safe_fprintf(&summary, "EXCEPTION_FLT_INEXACT_RESULT"); break;
case EXCEPTION_FLT_INVALID_OPERATION:
jl_safe_printf("EXCEPTION_FLT_INVALID_OPERATION"); break;
jl_safe_fprintf(&summary, "EXCEPTION_FLT_INVALID_OPERATION"); break;
case EXCEPTION_FLT_OVERFLOW:
jl_safe_printf("EXCEPTION_FLT_OVERFLOW"); break;
jl_safe_fprintf(&summary, "EXCEPTION_FLT_OVERFLOW"); break;
case EXCEPTION_FLT_STACK_CHECK:
jl_safe_printf("EXCEPTION_FLT_STACK_CHECK"); break;
jl_safe_fprintf(&summary, "EXCEPTION_FLT_STACK_CHECK"); break;
case EXCEPTION_FLT_UNDERFLOW:
jl_safe_printf("EXCEPTION_FLT_UNDERFLOW"); break;
jl_safe_fprintf(&summary, "EXCEPTION_FLT_UNDERFLOW"); break;
case EXCEPTION_ILLEGAL_INSTRUCTION:
jl_safe_printf("EXCEPTION_ILLEGAL_INSTRUCTION"); break;
jl_safe_fprintf(&summary, "EXCEPTION_ILLEGAL_INSTRUCTION"); break;
case EXCEPTION_IN_PAGE_ERROR:
jl_safe_printf("EXCEPTION_IN_PAGE_ERROR"); break;
jl_safe_fprintf(&summary, "EXCEPTION_IN_PAGE_ERROR"); break;
case EXCEPTION_INT_DIVIDE_BY_ZERO:
jl_safe_printf("EXCEPTION_INT_DIVIDE_BY_ZERO"); break;
jl_safe_fprintf(&summary, "EXCEPTION_INT_DIVIDE_BY_ZERO"); break;
case EXCEPTION_INT_OVERFLOW:
jl_safe_printf("EXCEPTION_INT_OVERFLOW"); break;
jl_safe_fprintf(&summary, "EXCEPTION_INT_OVERFLOW"); break;
case EXCEPTION_INVALID_DISPOSITION:
jl_safe_printf("EXCEPTION_INVALID_DISPOSITION"); break;
jl_safe_fprintf(&summary, "EXCEPTION_INVALID_DISPOSITION"); break;
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
jl_safe_printf("EXCEPTION_NONCONTINUABLE_EXCEPTION"); break;
jl_safe_fprintf(&summary, "EXCEPTION_NONCONTINUABLE_EXCEPTION"); break;
case EXCEPTION_PRIV_INSTRUCTION:
jl_safe_printf("EXCEPTION_PRIV_INSTRUCTION"); break;
jl_safe_fprintf(&summary, "EXCEPTION_PRIV_INSTRUCTION"); break;
case EXCEPTION_SINGLE_STEP:
jl_safe_printf("EXCEPTION_SINGLE_STEP"); break;
jl_safe_fprintf(&summary, "EXCEPTION_SINGLE_STEP"); break;
case EXCEPTION_STACK_OVERFLOW:
jl_safe_printf("EXCEPTION_STACK_OVERFLOW"); break;
jl_safe_fprintf(&summary, "EXCEPTION_STACK_OVERFLOW"); break;
default:
jl_safe_printf("UNKNOWN"); break;
jl_safe_fprintf(&summary, "UNKNOWN"); break;
}
jl_safe_fprintf(&summary, " at 0x%zx -- ", (size_t)ExceptionInfo->ExceptionRecord->ExceptionAddress);
jl_fprint_native_codeloc(&summary, (uintptr_t)ExceptionInfo->ExceptionRecord->ExceptionAddress);
ios_write(&full_error, summary.buf, ios_pos(&summary));
ios_puts("\nSee Application log in Event Viewer for more information.\n", &summary);

jl_fprint_critical_error(&full_error, 0, 0, ExceptionInfo->ContextRecord, ct);

// First print to STDERR
ios_write_direct(ios_safe_stderr, &full_error);

// Secondly print to Application log
HANDLE event_source = RegisterEventSourceW(NULL, L"julia");
if (event_source != INVALID_HANDLE_VALUE) {
ios_putc('\0', &full_error);
const wchar_t *strings[] = { ios_utf8_to_wchar(full_error.buf) };
ReportEventW(
event_source, EVENTLOG_ERROR_TYPE, /* category */ 0, /* event_id */ (DWORD)0xE0000000L,
/* user_sid */ NULL, /* n_strings */ 1, /* data_size */ 0, strings, /* data */ NULL
);
free(strings[0]);

if (jl_options.alert_on_critical_error) {
ios_putc('\0', &summary);
const wchar_t *message = ios_utf8_to_wchar(summary.buf);
MessageBoxW(NULL, message, /* title */ L"fatal error in libjulia",
MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL);
free(message);
}
}
jl_safe_printf(" at 0x%zx -- ", (size_t)ExceptionInfo->ExceptionRecord->ExceptionAddress);
jl_fprint_native_codeloc(ios_safe_stderr, (uintptr_t)ExceptionInfo->ExceptionRecord->ExceptionAddress);

jl_fprint_critical_error(ios_safe_stderr, 0, 0, ExceptionInfo->ContextRecord, ct);
ios_close(&summary);
ios_close(&full_error);
static int recursion = 0;
if (recursion++)
exit(1);
Expand Down
2 changes: 0 additions & 2 deletions src/staticdata.c
Original file line number Diff line number Diff line change
Expand Up @@ -3458,8 +3458,6 @@ JL_DLLEXPORT void jl_create_system_image(void **_native_data, jl_array_t *workli
return;
}

JL_DLLEXPORT size_t ios_write_direct(ios_t *dest, ios_t *src);

// Takes in a path of the form "usr/lib/julia/sys.so"
JL_DLLEXPORT jl_image_buf_t jl_preload_sysimg(const char *fname)
{
Expand Down
10 changes: 10 additions & 0 deletions src/support/ios.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <stdio.h> // for printf

#include "dtypes.h"
#include "uv.h"

#ifdef _OS_WINDOWS_
#include <malloc.h>
Expand Down Expand Up @@ -988,6 +989,15 @@ ios_t *ios_file(ios_t *s, const char *fname, int rd, int wr, int create, int tru
return NULL;
}

#ifdef _OS_WINDOWS_
const wchar_t *ios_utf8_to_wchar(const char *str) {
ssize_t wlen = uv_wtf8_length_as_utf16(str);
wchar_t *wstr = (wchar_t *)malloc_s(sizeof(wchar_t) * wlen);
uv_wtf8_to_utf16(str, wstr, wlen);
return wstr;
}
#endif // _OS_WINDOWS_

// Portable ios analogue of mkstemp: modifies fname to replace
// trailing XXXX's with unique ID and returns the file handle s
// for writing and reading.
Expand Down
5 changes: 5 additions & 0 deletions src/support/ios.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ extern void (*ios_set_io_wait_func)(int);
JL_DLLEXPORT size_t ios_read(ios_t *s, char *dest, size_t n) JL_NOTSAFEPOINT;
JL_DLLEXPORT size_t ios_readall(ios_t *s, char *dest, size_t n) JL_NOTSAFEPOINT;
JL_DLLEXPORT size_t ios_write(ios_t *s, const char *data, size_t n) JL_NOTSAFEPOINT;
JL_DLLEXPORT size_t ios_write_direct(ios_t *dest, ios_t *src) JL_NOTSAFEPOINT;
JL_DLLEXPORT int64_t ios_seek(ios_t *s, int64_t pos) JL_NOTSAFEPOINT; // absolute seek
JL_DLLEXPORT int64_t ios_seek_end(ios_t *s) JL_NOTSAFEPOINT;
JL_DLLEXPORT int64_t ios_skip(ios_t *s, int64_t offs); // relative seek
Expand Down Expand Up @@ -152,6 +153,10 @@ int ios_ungetc(int c, ios_t *s);
//wint_t ios_ungetwc(ios_t *s, wint_t wc);
#define ios_puts(str, s) ios_write(s, str, strlen(str))

#ifdef _OS_WINDOWS_
const wchar_t *ios_utf8_to_wchar(const char *str);
#endif

/*
With memory streams, mixed reads and writes are equivalent to performing
sequences of *p++, as either an lvalue or rvalue. File streams behave
Expand Down
35 changes: 31 additions & 4 deletions src/task.c
Original file line number Diff line number Diff line change
Expand Up @@ -732,11 +732,38 @@ JL_DLLEXPORT JL_NORETURN void jl_no_exc_handler(jl_value_t *e, jl_task_t *ct)
if (!e)
e = jl_current_exception(ct);

jl_printf((JL_STREAM*)STDERR_FILENO, "fatal: error thrown and no exception handler available.\n");
jl_static_show((JL_STREAM*)STDERR_FILENO, e);
jl_printf((JL_STREAM*)STDERR_FILENO, "\n");
jl_fprint_backtrace(ios_safe_stderr);
// Write error to memory first
ios_t s;
ios_mem(&s, 1024);
jl_safe_fprintf(&s, "fatal: error thrown and no exception handler available.\n");
jl_static_show((JL_STREAM*)&s, e);
jl_safe_fprintf(&s, "\n");
jl_fprint_backtrace(&s);

// Then to STDERR
ios_write_direct(ios_stderr, &s);

// Finally write to system log (if supported)
#ifdef _OS_WINDOWS_
HANDLE event_source = RegisterEventSourceW(NULL, L"julia");
if (event_source != INVALID_HANDLE_VALUE) {
ios_putc('\0', &s);
const wchar_t *strings[] = { ios_utf8_to_wchar(s.buf) };
ReportEventW(
event_source, EVENTLOG_ERROR_TYPE, /* category */ 0, /* event_id */ (DWORD)0xE0000000L,
/* user_sid */ NULL, /* n_strings */ 1, /* data_size */ 0, strings, /* data */ NULL
);
free(strings[0]);

if (jl_options.alert_on_critical_error) {
MessageBoxW(NULL, /* message */ L"fatal: error thrown and no exception handler available\n\n"
L"See Application log in Event Viewer for more information.",
/* title */ L"fatal error in libjulia", MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL);
}
}
#endif

ios_close(&s);
if (ct == NULL)
jl_raise(6);
jl_exit(1);
Expand Down
15 changes: 14 additions & 1 deletion stdlib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ include $(JULIAHOME)/deps/*.version

VERSDIR := v$(shell cut -d. -f1-2 < $(JULIAHOME)/VERSION)
DIRS := $(build_datarootdir)/julia/stdlib/$(VERSDIR) $(build_prefix)/manifest/$(VERSDIR)
LIBDIR := $(build_datarootdir)/lib/julia

$(foreach dir,$(DIRS),$(eval $(call dir_target,$(dir))))

JLLS = DSFMT GMP CURL LIBGIT2 LLVM LIBSSH2 LIBUV OPENSSL MPFR NGHTTP2 \
Expand Down Expand Up @@ -60,8 +62,19 @@ $(foreach module, $(STDLIBS), $(eval $(call symlink_target,$$(JULIAHOME)/stdlib/

STDLIBS_LINK_TARGETS := $(addprefix $(build_datarootdir)/julia/stdlib/$(VERSDIR)/,$(STDLIBS))

remove-gpl-libs:
ifeq ($(USE_GPL_LIBS),0)
@echo Removing GPL libs...
-rm -f $(LIBDIR)/libcholmod*
-rm -f $(LIBDIR)/libklu_cholmod*
-rm -f $(LIBDIR)/librbio*
-rm -f $(LIBDIR)/libspqr*
-rm -f $(LIBDIR)/libumfpack*
endif

getall get: $(addprefix get-, $(STDLIBS_EXT) $(JLL_NAMES))
install: version-check $(addprefix install-, $(STDLIBS_EXT) $(JLL_NAMES)) $(STDLIBS_LINK_TARGETS)

install: version-check $(addprefix install-, $(STDLIBS_EXT) $(JLL_NAMES)) $(STDLIBS_LINK_TARGETS) remove-gpl-libs
version-check: $(addprefix version-check-, $(STDLIBS_EXT))
uninstall: $(addprefix uninstall-, $(STDLIBS_EXT))
extstdlibclean:
Expand Down
Loading