diff --git a/pkg/urbit/Makefile b/pkg/urbit/Makefile index 2565bb8a5b..82db53003d 100644 --- a/pkg/urbit/Makefile +++ b/pkg/urbit/Makefile @@ -77,9 +77,9 @@ build/urbit-worker: $(common_objs) $(worker_objs) @mkdir -p ./build @$(CC) $^ $(LDFLAGS) -o $@ -%.o: %.c $(headers) +%.o: %.c $(headers) $(CCDEPS) @echo CC $< - @$(CC) -I./include $(CFLAGS) -c $< -o $@ + @$(CC) -I./include $(CFLAGS) $< $(CCEXTRA) -c -o $@ tags: $(all_srcs) $(headers) ctags $^ diff --git a/pkg/urbit/compat/mingw/compat.h b/pkg/urbit/compat/mingw/compat.h index 667c1ccf46..42f159baeb 100644 --- a/pkg/urbit/compat/mingw/compat.h +++ b/pkg/urbit/compat/mingw/compat.h @@ -12,6 +12,7 @@ int kill(pid_t pid, int signum); #define SIGUSR1 10 #define SIGALRM 14 #define SIGVTALRM 26 +#define SIGSTK 31 #define SIG_COUNT 32 #endif//_MINGW_IO_H \ No newline at end of file diff --git a/pkg/urbit/compat/mingw/poor-mans-nix-shell.sh b/pkg/urbit/compat/mingw/poor-mans-nix-shell.sh index ca54e63723..9cb37cb536 100644 --- a/pkg/urbit/compat/mingw/poor-mans-nix-shell.sh +++ b/pkg/urbit/compat/mingw/poor-mans-nix-shell.sh @@ -1,5 +1,5 @@ # ensure required mingw packages are installed -mpkgs=(cmake curl gcc jq libsigsegv libuv make wslay) +mpkgs=(cmake curl gcc jq libuv make wslay) pacman -S --needed autoconf automake-wrapper libtool patch ${mpkgs[@]/#/mingw-w64-x86_64-} declare -a cdirs diff --git a/pkg/urbit/compat/mingw/seh_handler_decorator.cc b/pkg/urbit/compat/mingw/seh_handler_decorator.cc new file mode 100644 index 0000000000..1ef350c7c2 --- /dev/null +++ b/pkg/urbit/compat/mingw/seh_handler_decorator.cc @@ -0,0 +1,65 @@ +#include +#include + +enum { INIT, CPAR, DQ, DQS, SQ, SQS }; +char line[1 << 16]; + +/* seh_handler_decorator: registers u3_exception_handler for all non-inline functions +*/ +int main(int argc, const char* argv[]) +{ + if (argc != 2) + return 1; + + int c, state = INIT, curly = 0, emit = 0; + + while (fgets(line, sizeof(line), stdin)) + { + if (line[0] == '#') + { + emit = !!strstr(line, argv[1]); + fputs(line, stdout); + } + else + for (int i = 0; line[i]; i++) + { + switch (state) { + case INIT: + case CPAR: + switch (line[i]) { + case ' ': + case '\t': + case '\n': + case '\r': + case '\f': break; + case '{': curly++; if (emit && curly == 1 && state == CPAR) goto emit_handler; goto reset; + case '}': curly--; goto reset; + case '"': state = DQ; break; + case '\'': state = SQ; break; + case ')': state = CPAR; break; + reset: + default: state = INIT; break; + } break; + case DQ: + switch (line[i]) { + case '\\': state = DQS; break; + case '"': state = INIT; break; + } break; + case DQS: state = DQ; break; + case SQ: + switch (line[i]) { + case '\\': state = SQS; break; + case '\'': state = INIT; break; + } break; + case SQS: state = SQ; break; + } + fputc(line[i], stdout); + continue; + emit_handler: + fputs("{__asm__(\".seh_handler u3_exception_handler,@except\\n\");", stdout); + state = INIT; + } + } + + return 0; +} diff --git a/pkg/urbit/compat/mingw/seh_handler_decorator.mk b/pkg/urbit/compat/mingw/seh_handler_decorator.mk new file mode 100644 index 0000000000..e02a569189 --- /dev/null +++ b/pkg/urbit/compat/mingw/seh_handler_decorator.mk @@ -0,0 +1,6 @@ +sehdexe := build/seh_handler_decorator.exe +CCDEPS := $(CCDEPS) $(sehdexe) +CCEXTRA = -E -o -|$(sehdexe) $<|$(CC) $(CFLAGS) -x cpp-output - + +$(sehdexe): compat/mingw/seh_handler_decorator.cc + @$(CC) $< -o $@ diff --git a/pkg/urbit/configure b/pkg/urbit/configure index e9d1fa74cb..3789b397dc 100755 --- a/pkg/urbit/configure +++ b/pkg/urbit/configure @@ -111,6 +111,7 @@ case $(tr A-Z a-z <<< $os) in CFLAGS="${CFLAGS-} -O3 -g" fi + deps="${deps/sigsegv}" compat="${compat-} mingw" CFLAGS="${CFLAGS-} ${cdirs[@]}" LDFLAGS="${LDFLAGS-} ${ldirs[@]} -static" diff --git a/pkg/urbit/daemon/main.c b/pkg/urbit/daemon/main.c index ee91948225..7912560a86 100644 --- a/pkg/urbit/daemon/main.c +++ b/pkg/urbit/daemon/main.c @@ -5,7 +5,9 @@ #define C3_GLOBAL #include "all.h" #include "vere/vere.h" +#if !defined(U3_OS_mingw) #include +#endif #include #include #include @@ -512,9 +514,11 @@ report(void) { printf("urbit %s\n", URBIT_VERSION); printf("gmp: %s\n", gmp_version); +#if !defined(U3_OS_mingw) printf("sigsegv: %d.%d\n", (libsigsegv_version >> 8) & 0xff, libsigsegv_version & 0xff); +#endif printf("openssl: %s\n", SSLeay_version(SSLEAY_VERSION)); printf("libuv: %s\n", uv_version_string()); printf("libh2o: %d.%d.%d\n", diff --git a/pkg/urbit/noun/manage.c b/pkg/urbit/noun/manage.c index 298ef0a650..4c2abe90ac 100644 --- a/pkg/urbit/noun/manage.c +++ b/pkg/urbit/noun/manage.c @@ -8,7 +8,6 @@ #include #include #include -#include #include // XX stack-overflow recovery should be gated by -a @@ -83,12 +82,38 @@ // static rsignal_jmpbuf u3_Signal; +#if defined(U3_OS_mingw) +/* u3_exception_handler: replaces libsigsegv on MingW +*/ +EXCEPTION_DISPOSITION u3_exception_handler( + IN PEXCEPTION_RECORD ExceptionRecord, + IN ULONG64 EstablisherFrame, + IN OUT PCONTEXT ContextRecord, + IN OUT PDISPATCHER_CONTEXT DispatcherContext) +{ + if (ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && + ExceptionRecord->ExceptionInformation[0] == 1 && + u3e_fault((void*)ExceptionRecord->ExceptionInformation[1], 1)) + { + return ExceptionContinueExecution; + } + + if (ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW) { + rsignal_raise(SIGSTK); + } + + return ExceptionContinueSearch; +} +#else +#include + #ifndef SIGSTKSZ # define SIGSTKSZ 16384 #endif #ifndef NO_OVERFLOW static uint8_t Sigstk[SIGSTKSZ]; #endif +#endif #if 0 /* _cm_punt(): crudely print trace. @@ -135,17 +160,25 @@ static void _cm_overflow(void *arg1, void *arg2, void *arg3) static void _cm_signal_handle(c3_l sig_l) { +#ifndef U3_OS_mingw if ( c3__over == sig_l ) { +#ifndef NO_OVERFLOW sigsegv_leave_handler(_cm_overflow, NULL, NULL, NULL); - } - else { +#endif + } else +#endif + { u3m_signal(sig_l); } } #ifndef NO_OVERFLOW static void +#ifndef U3_OS_mingw _cm_signal_handle_over(int emergency, stackoverflow_context_t scp) +#else +_cm_signal_handle_over(int x) +#endif { _cm_signal_handle(c3__over); } @@ -336,7 +369,11 @@ _cm_signal_deep(c3_w mil_w) } #ifndef NO_OVERFLOW +#ifndef U3_OS_mingw stackoverflow_install_handler(_cm_signal_handle_over, Sigstk, SIGSTKSZ); +#else + rsignal_install_handler(SIGSTK, _cm_signal_handle_over); +#endif #endif rsignal_install_handler(SIGINT, _cm_signal_handle_intr); rsignal_install_handler(SIGTERM, _cm_signal_handle_term); @@ -376,7 +413,11 @@ _cm_signal_done() rsignal_deinstall_handler(SIGVTALRM); #ifndef NO_OVERFLOW +#ifndef U3_OS_mingw stackoverflow_deinstall_handler(); +#else + rsignal_deinstall_handler(SIGSTK); +#endif #endif { struct itimerval itm_u; @@ -1624,10 +1665,12 @@ _cm_limits(void) static void _cm_signals(void) { +# if !defined(U3_OS_mingw) if ( 0 != sigsegv_install_handler(u3e_fault) ) { u3l_log("boot: sigsegv install failed\n"); exit(1); } +# endif # if defined(U3_OS_PROF) // Block SIGPROF, so that if/when we reactivate it on the