Fix ev thread swallowing error in some case.

This commit is contained in:
Calvin Rose 2021-08-27 11:46:42 -05:00
parent 0ab96b8e47
commit ab740f92db
4 changed files with 33 additions and 11 deletions

View File

@ -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));

View File

@ -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++) {

View File

@ -76,6 +76,9 @@ typedef struct {
} JanetCFunRegistry;
struct JanetVM {
/* Place for user data */
void *user;
/* Top level dynamic bindings */
JanetTable *top_dyns;

View File

@ -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;