From ab740f92dba4868eb6f10f20b185b5f3f43a566c Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Fri, 27 Aug 2021 11:46:42 -0500 Subject: [PATCH] Fix ev thread swallowing error in some case. --- src/core/ev.c | 33 ++++++++++++++++++++++++--------- src/core/marsh.c | 6 ++++-- src/core/state.h | 3 +++ src/core/vm.c | 2 ++ 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/core/ev.c b/src/core/ev.c index c447ef96..5493f2bd 100644 --- a/src/core/ev.c +++ b/src/core/ev.c @@ -2472,12 +2472,12 @@ static JanetEVGenericMessage janet_go_thread_subr(JanetEVGenericMessage args) { } /* Get supervsior */ - void *supervisor = NULL; if (flags & 0x8) { Janet sup = janet_unmarshal(nextbytes, endbytes - nextbytes, JANET_MARSHAL_UNSAFE, NULL, &nextbytes); - supervisor = janet_unwrap_pointer(sup); + /* Hack - use a global variable to avoid longjmp clobber */ + janet_vm.user = janet_unwrap_pointer(sup); } /* Set cfunction registry */ @@ -2506,17 +2506,32 @@ static JanetEVGenericMessage janet_go_thread_subr(JanetEVGenericMessage args) { JANET_MARSHAL_UNSAFE, NULL, &nextbytes); if (!janet_checktype(fiberv, JANET_FIBER)) janet_panicf("expected fiber, got %v", fiberv); JanetFiber *fiber = janet_unwrap_fiber(fiberv); - fiber->supervisor_channel = supervisor; + fiber->supervisor_channel = janet_vm.user; janet_schedule(fiber, value); janet_loop(); args.tag = JANET_EV_TCTAG_NIL; } else { - if (janet_checktype(tstate.payload, JANET_STRING)) { - args.tag = JANET_EV_TCTAG_ERR_STRINGF; - args.argp = strdup((const char *) janet_unwrap_string(tstate.payload)); + void *supervisor = janet_vm.user; + if (NULL != supervisor) { + /* Got a supervisor, write error there */ + Janet pair[] = { + janet_ckeywordv("error"), + tstate.payload + }; + janet_channel_push((JanetChannel *)supervisor, + janet_wrap_tuple(janet_tuple_n(pair, 2)), 2); + } else if (flags & 0x1) { + /* No wait, just print to stderr */ + janet_eprintf("thread start failure: %v\n", tstate.payload); } else { - args.tag = JANET_EV_TCTAG_ERR_STRING; - args.argp = "failed to start thread"; + /* Make ev/thread call from parent thread error */ + if (janet_checktype(tstate.payload, JANET_STRING)) { + args.tag = JANET_EV_TCTAG_ERR_STRINGF; + args.argp = strdup((const char *) janet_unwrap_string(tstate.payload)); + } else { + args.tag = JANET_EV_TCTAG_ERR_STRING; + args.argp = "failed to start thread"; + } } } janet_restore(&tstate); @@ -2559,7 +2574,7 @@ JANET_CORE_FN(cfun_ev_thread, janet_marshal(buffer, janet_wrap_abstract(supervisor), NULL, JANET_MARSHAL_UNSAFE); } if (!(flags & 0x4)) { - janet_assert(janet_vm.registry_count <= UINT32_MAX, "assert failed size check"); + janet_assert(janet_vm.registry_count <= INT32_MAX, "assert failed size check"); uint32_t temp = (uint32_t) janet_vm.registry_count; janet_buffer_push_bytes(buffer, (uint8_t *) &temp, sizeof(temp)); janet_buffer_push_bytes(buffer, (uint8_t *) janet_vm.registry, (int32_t) janet_vm.registry_count * sizeof(JanetCFunRegistry)); diff --git a/src/core/marsh.c b/src/core/marsh.c index a9912190..47eff301 100644 --- a/src/core/marsh.c +++ b/src/core/marsh.c @@ -953,6 +953,7 @@ static const uint8_t *unmarshal_one_fiber( fiber->data = NULL; fiber->child = NULL; fiber->env = NULL; + fiber->last_value = janet_wrap_nil(); #ifdef JANET_EV fiber->waiting = NULL; fiber->sched_id = 0; @@ -1257,7 +1258,7 @@ static const uint8_t *unmarshal_one( data++; int32_t len = readnat(st, &data); if (len > 255) { - janet_panicf("invalid function"); + janet_panicf("invalid function - too many environments (%d)", len); } func = janet_gcalloc(JANET_MEMORY_FUNCTION, sizeof(JanetFunction) + len * sizeof(JanetFuncEnv)); @@ -1265,7 +1266,8 @@ static const uint8_t *unmarshal_one( janet_v_push(st->lookup, *out); data = unmarshal_one_def(st, data, &def, flags + 1); if (def->environments_length != len) { - janet_panicf("invalid function"); + janet_panicf("invalid function - env count does not match def (%d != %d)", + len, def->environments_length); } func->def = def; for (int32_t i = 0; i < def->environments_length; i++) { diff --git a/src/core/state.h b/src/core/state.h index b6ee5f2f..b9106631 100644 --- a/src/core/state.h +++ b/src/core/state.h @@ -76,6 +76,9 @@ typedef struct { } JanetCFunRegistry; struct JanetVM { + /* Place for user data */ + void *user; + /* Top level dynamic bindings */ JanetTable *top_dyns; diff --git a/src/core/vm.c b/src/core/vm.c index 27e200c1..75683a4e 100644 --- a/src/core/vm.c +++ b/src/core/vm.c @@ -1520,6 +1520,7 @@ int janet_init(void) { janet_vm.root_capacity = 0; /* Scratch memory */ + janet_vm.user = NULL; janet_vm.scratch_mem = NULL; janet_vm.scratch_len = 0; janet_vm.scratch_cap = 0; @@ -1579,6 +1580,7 @@ void janet_deinit(void) { janet_vm.abstract_registry = NULL; janet_vm.core_env = NULL; janet_vm.top_dyns = NULL; + janet_vm.user = NULL; janet_free(janet_vm.traversal_base); janet_vm.fiber = NULL; janet_vm.root_fiber = NULL;