- blocking stdlib calls that PARK (net.accept, socket read/write, time.sleep, a child wait) no longer restart the syscall when the stop flag is set on an interruption: a server sitting in accept ignored SIGTERM and only `kill -9` ended it - a stop is NOT a trap -- builtin.h's WO_SYS_STOPPED carries no error record and no catch handler sees it (`try` must not swallow SIGTERM); the VM unwinds the whole stack through the same drop machinery an uncaught trap uses, so nothing leaks on the way out - wo_vm_call gained a third outcome (1 = stopped); the CLI maps it to the status the program's own `return 0` would have given, and a regular-file read keeps its plain EINTR retry -- it does not park - an ASSIGNMENT was not an ownership boundary: `api_key = j.mcp.apiKey` moved the field pointer into the local, so the local aliased the record and the first unwind freed the same string twice (SIGSEGV in class_free). `let` copied a Text place, assignment now does too -- the same double free was latent on the normal exit path, hidden by the order the compiler happens to emit drops in - log-watcher-accept is 7 checks: the seventh is the stop itself, with the hard kill demoted to a fallback whose use is the failure - measured under ASan: mcp parked, mcp after traffic, watch and run all exit rc 0 with zero leaks; SIGINT behaves as SIGTERM - gates: oop-accept ALL CRITERIA MET, oop-e2e 71/0, woc-test 565/0, wovm-test green, log-watcher 7/0 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
28 lines
1.3 KiB
C
28 lines
1.3 KiB
C
/* builtin.h — runtime services bytecode can't express (spec §3/§5):
|
|
* now/print/print_int/words plus the container bridge to cont.c. One
|
|
* dispatcher: takes the VM, the current frame's registers, and the
|
|
* instruction; 0 = ok, else a WO_T_* trap code with *msg set. */
|
|
#ifndef WO_BUILTIN_H
|
|
#define WO_BUILTIN_H
|
|
|
|
#include "vm.h"
|
|
|
|
/* Not a trap code: the stop flag (SIGTERM/SIGINT, armed by `env.stopping`)
|
|
* was set when a BLOCKING call was interrupted, so the call does not restart
|
|
* the syscall — it hands this back and the VM ends the program with it. A
|
|
* service parked in `accept` otherwise never observes the flag and only
|
|
* `kill -9` ends it. Negative so it cannot collide with a WO_T_* code, and
|
|
* deliberately NOT catchable: `try` must not be able to swallow a stop. */
|
|
#define WO_SYS_STOPPED (-2)
|
|
|
|
int wo_builtin(wo_vm *vm, uint64_t *R, uint32_t ins, const char **msg);
|
|
|
|
/* The systems stdlib's OS half (runtime/src/sysio.c): same contract as
|
|
* wo_builtin above — 0 on success, a WO_T_* code with *msg set on failure.
|
|
* wo_builtin dispatches every id at or above WO_B_SYS_FIRST here. */
|
|
int wo_builtin_sys(wo_vm *vm, uint64_t *R, uint32_t ins, const char **msg);
|
|
|
|
/* json.encode / json.decode (runtime/src/json.c), same contract again. */
|
|
int wo_builtin_json(wo_vm *vm, uint64_t *R, uint32_t ins, const char **msg);
|
|
|
|
#endif /* WO_BUILTIN_H */
|