Skip to content

Commit

Permalink
mach-spawn: fix spurious InterruptException
Browse files Browse the repository at this point in the history
this was a bug in our libuv fork triggering a bug in the mach kernel

code must be careful to never use sigprocmask, setjmp, longjmp, or
similar such thread-unsafe functions to avoid this documented unspecified behavior
  • Loading branch information
vtjnash committed Dec 24, 2016
1 parent cfaae3a commit 15882bc
Show file tree
Hide file tree
Showing 13 changed files with 49 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0e6ec181c8bfd322a17dbd843b2b8ebb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
4bf9c8b16617691b70ea43c667ecc575d2a06b3d0c347b949d10360c012138585a13ecea5e18de81b1585a96cf7734b7cc3d6072490898f1d5531c702cf5afab

This file was deleted.

This file was deleted.

2 changes: 1 addition & 1 deletion deps/libuv.version
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
LIBUV_BRANCH=julia-uv1.9.0
LIBUV_SHA1=8d5131b6c1595920dd30644cd1435b4f344b46c8
LIBUV_SHA1=52d72a52cc7ccd570929990f010ed16e2ec604c8
1 change: 0 additions & 1 deletion src/flisp/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <setjmp.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>
Expand Down
5 changes: 2 additions & 3 deletions src/flisp/flisp.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <setjmp.h>
#include <stdint.h>
#include <stdarg.h>
#include <assert.h>
Expand Down Expand Up @@ -117,7 +116,7 @@ static void free_readstate(fl_readstate_t *rs)
fl_exception_context_t _ctx; int l__tr, l__ca; \
_ctx.sp=fl_ctx->SP; _ctx.frame=fl_ctx->curr_frame; _ctx.rdst=fl_ctx->readstate; _ctx.prev=fl_ctx->exc_ctx; \
_ctx.ngchnd = fl_ctx->N_GCHND; fl_ctx->exc_ctx = &_ctx; \
if (!setjmp(_ctx.buf)) \
if (!fl_setjmp(_ctx.buf)) \
for (l__tr=1; l__tr; l__tr=0, (void)(fl_ctx->exc_ctx=fl_ctx->exc_ctx->prev))

#define FL_CATCH(fl_ctx) \
Expand Down Expand Up @@ -156,7 +155,7 @@ void fl_raise(fl_context_t *fl_ctx, value_t e)
fl_exception_context_t *thisctx = fl_ctx->exc_ctx;
if (fl_ctx->exc_ctx->prev) // don't throw past toplevel
fl_ctx->exc_ctx = fl_ctx->exc_ctx->prev;
longjmp(thisctx->buf, 1);
fl_longjmp(thisctx->buf, 1);
}

static value_t make_error_msg(fl_context_t *fl_ctx, const char *format, va_list args)
Expand Down
21 changes: 19 additions & 2 deletions src/flisp/flisp.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,25 @@ fixnum_t tofixnum(fl_context_t *fl_ctx, value_t v, const char *fname);
char *tostring(fl_context_t *fl_ctx, value_t v, const char *fname);

/* error handling */
#if defined(_OS_WINDOWS_)
#define fl_jmp_buf jmp_buf
#if defined(_COMPILER_MINGW_)
int __attribute__ ((__nothrow__,__returns_twice__)) (jl_setjmp)(jmp_buf _Buf);
__declspec(noreturn) __attribute__ ((__nothrow__)) void (jl_longjmp)(jmp_buf _Buf, int _Value);
#else
int (jl_setjmp)(jmp_buf _Buf);
void (jl_longjmp)(jmp_buf _Buf, int _Value);
#endif
#define fl_setjmp(a) jl_setjmp(a)
#define fl_longjmp(a, b) jl_longjmp((a), (b))
#else // !_OS_WINDOWS_
#define fl_jmp_buf sigjmp_buf
#define fl_setjmp(a) sigsetjmp((a), 0)
#define fl_longjmp(a, b) siglongjmp((a), (b))
#endif

typedef struct _ectx_t {
jmp_buf buf;
fl_jmp_buf buf;
uint32_t sp;
uint32_t frame;
uint32_t ngchnd;
Expand All @@ -179,7 +196,7 @@ typedef struct _ectx_t {
#define FL_TRY_EXTERN(fl_ctx) \
fl_exception_context_t _ctx; int l__tr, l__ca; \
fl_savestate(fl_ctx, &_ctx); fl_ctx->exc_ctx = &_ctx; \
if (!setjmp(_ctx.buf)) \
if (!fl_setjmp(_ctx.buf)) \
for (l__tr=1; l__tr; l__tr=0, (void)(fl_ctx->exc_ctx=fl_ctx->exc_ctx->prev))

#define FL_CATCH_EXTERN(fl_ctx) \
Expand Down
1 change: 0 additions & 1 deletion src/flisp/iostream.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include <string.h>
#include <assert.h>
#include <sys/types.h>
#include <setjmp.h>
#include "flisp.h"

#ifdef __cplusplus
Expand Down
1 change: 0 additions & 1 deletion src/flisp/string.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <setjmp.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>
Expand Down
1 change: 0 additions & 1 deletion src/flisp/table.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include <string.h>
#include <assert.h>
#include <sys/types.h>
#include <setjmp.h>
#include "flisp.h"
#include "equalhash.h"

Expand Down
8 changes: 4 additions & 4 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -1537,11 +1537,11 @@ JL_DLLEXPORT void jl_pop_handler(int n);

#if defined(_OS_WINDOWS_)
#if defined(_COMPILER_MINGW_)
int __attribute__ ((__nothrow__,__returns_twice__)) jl_setjmp(jmp_buf _Buf);
__declspec(noreturn) __attribute__ ((__nothrow__)) void jl_longjmp(jmp_buf _Buf,int _Value);
int __attribute__ ((__nothrow__,__returns_twice__)) (jl_setjmp)(jmp_buf _Buf);
__declspec(noreturn) __attribute__ ((__nothrow__)) void (jl_longjmp)(jmp_buf _Buf, int _Value);
#else
int jl_setjmp(jmp_buf _Buf);
void jl_longjmp(jmp_buf _Buf,int _Value);
int (jl_setjmp)(jmp_buf _Buf);
void (jl_longjmp)(jmp_buf _Buf, int _Value);
#endif
#define jl_setjmp_f jl_setjmp
#define jl_setjmp_name "jl_setjmp"
Expand Down
22 changes: 21 additions & 1 deletion src/signals-unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -527,10 +527,30 @@ static void *signal_listener(void *arg)
unw_context_t *signal_context;
int sig, critical, profile;
int i;
// prevent this thread from being used to run other,
// potentially blocking signal handlers
sigfillset(&sset);
sigdelset(&sset, SIGSEGV);
sigdelset(&sset, SIGILL);
sigdelset(&sset, SIGKILL);
sigdelset(&sset, SIGBUS);
sigdelset(&sset, SIGABRT);
sigdelset(&sset, SIGSYS);
pthread_sigmask(SIG_SETMASK, &sset, 0);

jl_sigsetset(&sset);
while (1) {
profile = 0;
sigwait(&sset, &sig);
sig = 0;
errno = 0;
if (sigwait(&sset, &sig)) {
sig = SIGABRT; // this branch can't occur, unless we had stack memory corruption of sset
}
if (!sig) {
// this should never happen, but it has been observed to occur on some buggy kernels (mach)
// when sigprocmask is incorrectly used on some other thread, instead of pthread_sigmask
continue;
}
#ifndef HAVE_MACH
# ifdef HAVE_ITIMER
profile = (sig == SIGPROF);
Expand Down

0 comments on commit 15882bc

Please sign in to comment.