diff --git a/scripts/engine.cm b/scripts/engine.cm index f8a98a2a..e0e04f9e 100644 --- a/scripts/engine.cm +++ b/scripts/engine.cm @@ -512,8 +512,8 @@ $_.stop = function stop(actor) { throw new Error('Can only call stop on an actor.') if (!underlings.has(actor[ACTORDATA].id)) throw new Error('Can only call stop on an underling or self.') - - sys_msg(actor, {kind:"stop"}) + + sys_msg(actor, "stop") } $_.stop[cell.DOC] = "The stop function stops an underling." @@ -712,14 +712,13 @@ function handle_sysym(msg, from) { switch(msg.kind) { case 'stop': - if (from[ACTORDATA].id !== overling[ACTORDATA].id) - log.error(`Got a message from a random actor ${msg.id} to stop`) - else - disrupt("got stop message") + disrupt("got stop message") break case 'underling': var greeter = greeters[from[ACTORDATA].id] if (greeter) greeter(msg.message) + if (msg.message.type == 'disrupt') + underlings.delete(from[ACTORDATA].id) break case 'contact': if (portal_fn) { @@ -810,10 +809,14 @@ var progContent = io.slurp(prog) var prog_script = `(function ${cell.args.program.name()}_start($_, arg) { var args = arg; ${progContent} })` -var val = js.eval(cell.args.program, prog_script)($_, cell.args.arg) -if (val) - throw new Error('Program must not return anything'); +// queue up its first turn instead of run immediately -send_messages() +var startfn = js.eval(cell.args.program, prog_script); +$_.delay(_ => { + var val = startfn($_, cell.args.arg); + + if (val) + throw new Error('Program must not return anything'); +}, 0) })() \ No newline at end of file diff --git a/scripts/test.ce b/scripts/test.ce index 97499425..5ba03a4e 100644 --- a/scripts/test.ce +++ b/scripts/test.ce @@ -14,7 +14,8 @@ if (arg.length === 0) 'text', 'http', 'use', - 'parseq' + 'parseq', + 'kill' ] for (var test of def) diff --git a/source/cell.c b/source/cell.c index 75410a63..e7869992 100644 --- a/source/cell.c +++ b/source/cell.c @@ -702,8 +702,6 @@ int uncaught_exception(JSContext *js, JSValue v) return 1; } - printf("UNCAUGHT EXCEPTION IN ACTOR %s\n", rt->id); - JSValue exp = JS_GetException(js); JSValue ret = JS_Call(js, rt->on_exception, JS_UNDEFINED, 1, &exp); diff --git a/source/qjs_actor.c b/source/qjs_actor.c index 512e37bd..1f6ebd6b 100644 --- a/source/qjs_actor.c +++ b/source/qjs_actor.c @@ -88,10 +88,29 @@ JSC_CCALL(os_mailbox_push, const char *id = JS_ToCString(js, argv[0]); int exist = actor_exists(id); - JS_FreeCString(js,id); - if (!exist) - return JS_ThrowInternalError(js, "No mailbox found for given ID"); + if (!exist) { + JS_FreeCString(js,id); + return JS_ThrowInternalError(js, "No mailbox found for given ID"); + } + + cell_rt *target = get_actor(id); + JS_FreeCString(js,id); + + JSValue sys = JS_GetPropertyStr(js, argv[1], "__SYSTEM__"); + if (!JS_IsUndefined(sys)) { + const char *k = JS_ToCString(js,sys); + int stop = 0; + if (strcmp(k, "stop") == 0) { + stop = 1; + actor_disrupt(target); + } + JS_FreeValue(js,sys); + JS_FreeCString(js,k); + + if (stop) return JS_UNDEFINED; + } + void *data = value2wota(js, argv[1], JS_UNDEFINED); const char *err = send_message(id, data); @@ -138,11 +157,6 @@ JSC_SCALL(actor_setname, rt->name = strdup(str); ) -JSC_CCALL(actor_testfn, - cell_rt *crt = js2actor(js, argv[0]); - printf("actor? %p\n", crt); -) - JSC_CCALL(actor_on_exception, cell_rt *rt = JS_GetContextOpaque(js); JS_FreeValue(js, rt->on_exception); @@ -159,7 +173,6 @@ static const JSCFunctionListEntry js_actor_funcs[] = { MIST_FUNC_DEF(os, unneeded, 2), MIST_FUNC_DEF(actor, disrupt, 0), MIST_FUNC_DEF(actor, setname, 1), - MIST_FUNC_DEF(actor, testfn, 1), MIST_FUNC_DEF(actor, on_exception, 1), }; diff --git a/tests/hang.ce b/tests/hang.ce new file mode 100644 index 00000000..f2c96444 --- /dev/null +++ b/tests/hang.ce @@ -0,0 +1,5 @@ +log.console(`Going to start hanging ...`) + +while(1) { + // hang! +} diff --git a/tests/kill.ce b/tests/kill.ce new file mode 100644 index 00000000..d18456c8 --- /dev/null +++ b/tests/kill.ce @@ -0,0 +1,15 @@ +// This tests forceful killing of an underling that may even be in the middle of a turn + +$_.start(e => { + log.console(`got message from hanger: ${e.type}`) + if (e.type == 'greet') + $_.delay(_ => { + log.console(`sending stop message to hanger`) + $_.stop(e.actor) + }, 1) + + if (e.type == 'disrupt') { + log.console(`underling successfully killed.`) + $_.stop() + } +}, 'hang') \ No newline at end of file