Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
2301d97
fix(codegen): P0 — case-arm rebinding the scrutinee's name emitted C …
claude Jun 9, 2026
31208a0
fix(codegen): P0 — compiled tail loops never yielded; spawn storms di…
claude Jun 9, 2026
273cd78
fix(runtime): P1 — allocation failure now panics loud instead of SIGS…
claude Jun 9, 2026
9c0a409
docs: Round-7 audit report (Fable, June 2026) + two new known issues …
claude Jun 9, 2026
d8bf46f
fix(lang): converge the two execution paths + make every failure loud
claude Jun 9, 2026
47e2015
test: dual-path conformance gate — every conform program must agree a…
claude Jun 9, 2026
bb52969
docs: error-model + new-surface reference; KNOWN_ISSUES — clear try/c…
claude Jun 9, 2026
48bd46f
feat(std): Std.map / Std.filter / Std.join — make the Elixir-shaped g…
claude Jun 9, 2026
fda588a
docs: README — conformance gate + current test counts + Std aliases; …
claude Jun 9, 2026
a47f14d
feat(gc): Phase 2.1 — LeakSanitizer lifecycle gate (make lsan-gate + …
claude Jun 9, 2026
2239288
feat(diag+lang): real source paths, module-qualified did-you-mean, st…
claude Jun 9, 2026
0e4337e
test+docs: Phase 2.2 scheduler-count matrix — bounded tests, S<3 skip…
claude Jun 9, 2026
76c44e0
perf(sched): O4 — bounded spin-before-park; cross-scheduler ping-pong…
claude Jun 9, 2026
df57d3c
docs: roadmap — Phase 2.1 + 2.2 DONE with findings; Round-7 table — O…
claude Jun 9, 2026
3f3b2bf
perf(boot): O5 — watchdog shutdown via condvar; hello wall time 110-1…
claude Jun 10, 2026
35283f6
test: spin-wedge reproducer + gc_slope probe timeout armor
claude Jun 10, 2026
78931d0
docs: P1 spin-gated deadlock entry; roadmap 2.2 amended; README start…
claude Jun 10, 2026
8603514
fix(runtime): three C11 data races flagged by TSan — volatile flags b…
claude Jun 10, 2026
92813f0
test: Phase 2.3 — make tsan-gate (msg ping-pong, msg+spin, 80k storm …
claude Jun 10, 2026
831d6ce
docs: roadmap — Phase 2.3 (TSan) DONE: gate + findings + the no-fiber…
claude Jun 10, 2026
437adc1
test+docs: O8 host-limit prints in the stress gate; Phase 2.4 audit r…
claude Jun 10, 2026
e8ddea1
fix(sched): P1 deadlock root-caused — Dekker StoreLoad bug in the rec…
claude Jun 10, 2026
4d2a692
docs: P1 deadlock -> Recently cleared with the full Dekker story; roa…
claude Jun 10, 2026
c635b5e
fix(parser): untrusted .sw can no longer OOM swc — receive-clause spi…
claude Jun 10, 2026
38a817a
fix(runtime): Phase 2.4 — race-free proc->state, timer peek, monitor-…
claude Jun 10, 2026
30e5497
fix(runtime): Phase 2.4 COMPLETE — supervisor/registry/monitor races …
claude Jun 10, 2026
f98288d
feat(gc): Phase 2.5 — allocation-failure injection gate (make alloc-f…
claude Jun 10, 2026
a72e32a
feat(soak): Phase 2.6 — mixed-workload soak harness (make soak); Phas…
claude Jun 10, 2026
ec1ded6
fix(json): Phase 3 — fuzz the JSON decoder; fix two heap-overflows + …
claude Jun 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions .github/workflows/linux-quickstart.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,65 @@ jobs:
make gc-slope
SW_SCHEDULERS=1 make gc-slope

- name: LeakSanitizer lifecycle gate (Phase 2.1 — Linux-only LSan)
# The slope gates catch UNBOUNDED growth; this catches BOUNDED leaks
# under their RSS noise floor. macOS Apple-clang ASAN has no LSan, so
# every other ASAN run uses detect_leaks=0 and is leak-blind — this
# Linux leg is the only real leak assertion in CI. Churns every
# lifecycle owner (timers fired+cancelled, supervisors killed, ETS
# replace/delete, spawns, compound messages), exits cleanly, and LSan
# asserts zero definitely-lost blocks at exit. Proven bidirectional
# (an injected unreachable block fails it). Advisory while it bakes;
# promote to blocking once green across a week of pushes.
continue-on-error: true
run: make lsan-gate

- name: ThreadSanitizer race gate (Phase 2.3/2.4 — msg, storm, phase 2/4/5)
# Runtime must be free of C11 data races on the message, spawn-storm,
# and GenServer/Supervisor/Agent/DynSup/StateMachine/ProcessGroup
# paths. Suppresses only the by-design warn-only watchdog scanner +
# sw_stats printer (tests/stress/tsan.supp).
run: make tsan-gate

- name: Allocation-failure injection (Phase 2.5 — no UAF/double-free on OOM)
# Fails the Nth value/region allocation across a 120-point sweep and
# asserts the ownership-transfer cleanup (spawn region, message copy,
# supervisor closures, ETS) never corrupts memory — only ever a clean
# completion or a loud OOM panic.
run: make alloc-fault

- name: Soak smoke (Phase 2.6 — 60s mixed workload, bounded RSS)
# Actor fan-out + supervisor crash/restart + ETS churn + timers in a
# tight loop for 60s; asserts clean exit and peak RSS under budget.
# The full 24h soak is the same binary (SOAK_SECONDS=86400) on a
# dedicated host — see PRODUCTION_ROADMAP.md 2.6.
run: make soak

- name: Scheduler-count matrix (Phase 2.2 — suite under S=1 and oversubscribed)
# The default-scheduler run above covers nproc; these legs cover the
# edges. S=1 found a real architecture issue (blocking curl client +
# in-process server deadlocks — the affected tests SKIP below 3
# schedulers, see KNOWN_ISSUES); S=8 oversubscribes the runner's
# cores so cross-scheduler interleavings get exercised. The per-test
# 180s timeout in run_tests.sh turns any future hang into a loud FAIL.
run: |
set -e
SW_SCHEDULERS=1 ./tests/sw/run_tests.sh
SW_SCHEDULERS=1 ./tests/sw/run_conform.sh
SW_SCHEDULERS=8 ./tests/sw/run_tests.sh
SW_SCHEDULERS=8 ./tests/sw/run_conform.sh

- name: Stress test (high-process-count race guard)
# Catches regressions in the high-spawn scheduler/mailbox path.
# The historical ctx-tear race is closed by per-slot generation
# counters + ctx_lock; the later spawn-storm crash cleared on
# native Linux x86_64 May 29, so any miss here is a regression.
run: make stress

- name: Fuzz (Phase 3 — untrusted-input boundaries under ASAN/UBSAN)
# 20k mutations per target over parser, JSON decoder (agent-facing
# boundary), distribution unmarshal, and HTTP header parser. Every
# external-input surface must be memory-safe on arbitrary bytes.
# fuzz-json found two real heap-overflows (number force-advance past
# NUL, backslash-at-EOF) on the first run — so this gate earns its keep.
run: make fuzz
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,4 @@ tests/sw/.build/
/2/

tests/stress/.build/
tests/soak/.build/
121 changes: 119 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ examples: swc libswarmrt
# pass/fail counts across all files. See tests/sw/run_tests.sh.
test-sw: swc libswarmrt
@./tests/sw/run_tests.sh
@./tests/sw/run_conform.sh

# Security regression: the curl-backed HTTP builtins must not pass
# caller-supplied URLs / headers through a shell. Builds the injection
Expand Down Expand Up @@ -267,12 +268,21 @@ FUZZ_RT := $(SRC_DIR)/swarmrt_native.c $(SRC_DIR)/swarmrt_asm.S $(SRC_DIR)/swarm
$(SRC_DIR)/swarmrt_http.c $(SRC_DIR)/swarmrt_pdf.c $(SRC_DIR)/swarmrt_varena.c
ASAN_FUZZ_ENV := ASAN_OPTIONS=detect_leaks=0:abort_on_error=1

.PHONY: fuzz fuzz-parse fuzz-marshal fuzz-http
.PHONY: fuzz fuzz-parse fuzz-marshal fuzz-http fuzz-json
fuzz-parse: dirs
$(FUZZ_CC) $(CFLAGS) $(SAN) -DSW_FUZZ_STANDALONE -Itests/fuzz \
tests/fuzz/fuzz_parse.c $(FUZZ_RT) -o $(BIN_DIR)/fuzz_parse $(LDFLAGS)
@$(ASAN_FUZZ_ENV) $(BIN_DIR)/fuzz_parse tests/fuzz/corpus/parse

# JSON decoder — the agent-facing input boundary (every LLM tool-call
# response / parsed HTTP body). Proves no crash/over-read/stack-overflow
# on malformed or adversarially-nested input (the corpus includes a
# 5000-deep array; g_jd_depth must bound it).
fuzz-json: dirs
$(FUZZ_CC) $(CFLAGS) $(SAN) -DSW_FUZZ_STANDALONE -Itests/fuzz \
tests/fuzz/fuzz_json.c $(FUZZ_RT) -o $(BIN_DIR)/fuzz_json $(LDFLAGS)
@$(ASAN_FUZZ_ENV) $(BIN_DIR)/fuzz_json tests/fuzz/corpus/json

fuzz-marshal: dirs
$(FUZZ_CC) $(CFLAGS) $(SAN) -DSW_FUZZ_STANDALONE -Itests/fuzz \
tests/fuzz/fuzz_marshal.c $(FUZZ_RT) -o $(BIN_DIR)/fuzz_marshal $(LDFLAGS)
Expand All @@ -286,7 +296,7 @@ fuzz-http: dirs
tests/fuzz/fuzz_http.c $(FUZZ_RT) -o $(BIN_DIR)/fuzz_http $(LDFLAGS)
@$(ASAN_FUZZ_ENV) $(BIN_DIR)/fuzz_http tests/fuzz/corpus/http

fuzz: fuzz-parse fuzz-marshal fuzz-http
fuzz: fuzz-parse fuzz-json fuzz-marshal fuzz-http

# GC v1 correctness gate: the copy-on-escape stress harness compiled with ASAN +
# SW_ARENA_POISON. Workers build compound values in their per-process arenas,
Expand Down Expand Up @@ -388,6 +398,72 @@ gc-slope: swc
[ $$rc -eq 0 ] && echo "gc-slope: PASS (bounded)" || echo "gc-slope: FAIL (unbounded)"; \
exit $$rc

# LeakSanitizer lifecycle gate (Phase 2.1) — Linux only (macOS Apple-clang
# ASAN ships no LSan; every other ASAN run here uses detect_leaks=0 and is
# leak-BLIND — see PRODUCTION_ROADMAP.md). Churns every lifecycle owner
# (timers fired+cancelled, supervisors killed, ETS replace/delete, spawns,
# compound messages), exits cleanly, and lets LSan assert zero
# definitely-lost blocks at exit. Parked-fiber stacks can't false-positive
# because at clean exit every process is gone; globals-reachable singletons
# are "still reachable" and not reported. Suppressions (each one a
# documented accepted-minor) live in tests/gc/lsan.supp.
.PHONY: lsan-gate
lsan-gate: swc
@if [ "$$(uname)" != "Linux" ]; then \
echo "lsan-gate: SKIP (LeakSanitizer requires Linux clang/gcc ASAN)"; exit 0; \
fi
@./bin/swc build --emit-c tests/gc/lsan_lifecycle.sw -o $(BIN_DIR)/_lsan_emit >/dev/null 2>&1 || true
$(FUZZ_CC) $(CFLAGS) -I$(SRC_DIR) -fsanitize=address -g -O1 -fno-stack-protector \
tests/gc/lsan_lifecycle.gen.c $(FUZZ_RT) -o $(BIN_DIR)/lsan_gate $(LDFLAGS)
@rm -f tests/gc/lsan_lifecycle.gen.c $(BIN_DIR)/_lsan_emit
@out=$$(SW_QUIET=1 SW_SCHEDULERS=1 \
ASAN_OPTIONS=detect_leaks=1:abort_on_error=0:exitcode=23 \
LSAN_OPTIONS=suppressions=tests/gc/lsan.supp:print_suppressions=1 \
timeout 240 $(BIN_DIR)/lsan_gate 2>&1); rc=$$?; \
echo "$$out" | tail -25; \
if ! echo "$$out" | grep -q "PROBE_OK"; then echo "lsan-gate: FAIL (probe did not complete)"; exit 1; fi; \
if [ $$rc -eq 23 ] || echo "$$out" | grep -q "definitely lost\|SUMMARY: AddressSanitizer.*leak"; then \
echo "lsan-gate: FAIL (leaks at exit)"; exit 1; fi; \
echo "lsan-gate: PASS (zero unsuppressed leaks at exit)"

# Allocation-failure injection gate (Phase 2.5). Builds the workload with
# -DSW_ALLOC_FAULT + ASAN and runs it once per fail-point N (SW_FAIL_ALLOC_AT),
# so the Nth value/region allocation fails exactly once. Each run must exit
# 0 (clean) or 1 (loud OOM/spawn panic) — BOTH fine. The gate FAILS only on
# an ASAN report (use-after-free / double-free / heap overflow): a fault that
# corrupted memory instead of unwinding. Sweeps a range that covers the
# spawn/send/supervise/ETS ownership-transfer sites. Linux/ASAN only.
.PHONY: alloc-fault
alloc-fault: swc
@if [ "$$(uname)" != "Linux" ]; then echo "alloc-fault: SKIP (needs Linux ASAN)"; exit 0; fi
@./bin/swc build --emit-c tests/gc/alloc_fault.sw -o $(BIN_DIR)/_af_emit >/dev/null 2>&1 || true
$(FUZZ_CC) $(CFLAGS) -I$(SRC_DIR) -fsanitize=address -DSW_ALLOC_FAULT -g -O1 -fno-stack-protector \
tests/gc/alloc_fault.gen.c $(FUZZ_RT) -o $(BIN_DIR)/alloc_fault $(LDFLAGS)
@rm -f tests/gc/alloc_fault.gen.c $(BIN_DIR)/_af_emit
@rc=0; faults=0; clean=0; \
for n in $$(seq 1 120); do \
out=$$(SW_QUIET=1 SW_SCHEDULERS=1 SW_FAIL_ALLOC_AT=$$n \
ASAN_OPTIONS=detect_leaks=0:abort_on_error=1 \
timeout 30 $(BIN_DIR)/alloc_fault 2>&1); \
ec=$$?; \
if echo "$$out" | grep -qE "AddressSanitizer|runtime error:|heap-use-after-free|double-free"; then \
echo "alloc-fault: FAIL at SW_FAIL_ALLOC_AT=$$n (memory error)"; \
echo "$$out" | grep -A8 "AddressSanitizer" | head -20; rc=1; break; \
fi; \
if echo "$$out" | grep -q "alloc_fault DONE"; then clean=$$((clean+1)); else faults=$$((faults+1)); fi; \
done; \
[ $$rc -eq 0 ] && echo "alloc-fault: PASS (120 fail-points: $$clean clean, $$faults loud-OOM, 0 memory errors)" \
|| exit 1

# Soak (Phase 2.6): mixed-workload (actor fan-out + supervisor crash/restart
# + ETS churn + timers) run for SOAK_SECONDS while sampling RSS. Asserts clean
# exit + peak RSS under budget — the whole mix stays flat under sustained
# churn, not just the per-owner slope probes. CI runs the 60s smoke; the full
# 24h soak is the same binary with SOAK_SECONDS=86400 on a dedicated host.
.PHONY: soak
soak: swc libswarmrt
@./tests/soak/run_soak.sh

# Stress: 80k-spawn microbench across default scheduler count and
# SW_SCHEDULERS=1. Defaults to 50 runs per variant and requires every
# run to print `ok 80000`. Requires native Linux x86_64 thread scheduling
Expand Down Expand Up @@ -478,3 +554,44 @@ stats:
@echo ""
@echo "=== Example Programs ==="
@find $(EXAMPLES_DIR) -name "*.sw" | xargs wc -l 2>/dev/null || echo " (none)"

# ThreadSanitizer gate (Phase 2.3). Builds the depth-1 message ping-pong
# and the 80k spawn storm under -fsanitize=thread and fails on any
# unsuppressed race. The fiber runtime is TSan-clean because cross-thread
# fiber migration synchronizes through the runq's C11 atomics — TSan sees
# the happens-before edges; no fiber annotations needed. Suppressions
# (tests/stress/tsan.supp) cover only the documented warn-only watchdog
# scanner. The storm runs its full 80k spawns — ~2 min under TSan.
.PHONY: tsan-gate
tsan-gate: swc
@./bin/swc build --emit-c tests/gc/slope_message.sw -o $(BIN_DIR)/_tsm_emit >/dev/null 2>&1 || true
$(FUZZ_CC) $(CFLAGS) -I$(SRC_DIR) -fsanitize=thread -g -O1 \
tests/gc/slope_message.gen.c $(FUZZ_RT) -o $(BIN_DIR)/tsan_msg $(LDFLAGS)
@./bin/swc build --emit-c tests/stress/bn.sw -o $(BIN_DIR)/_tsb_emit >/dev/null 2>&1 || true
$(FUZZ_CC) $(CFLAGS) -I$(SRC_DIR) -fsanitize=thread -g -O1 \
tests/stress/bn.gen.c $(FUZZ_RT) -o $(BIN_DIR)/tsan_storm $(LDFLAGS)
@rm -f tests/gc/slope_message.gen.c tests/stress/bn.gen.c $(BIN_DIR)/_tsm_emit $(BIN_DIR)/_tsb_emit
@# phase 2 (GenServer/Supervisor), 4 (Agent/DynSup), 5 (StateMachine/PG) are
@# all TSan-clean and gated here.
@for p in 2 4 5; do \
$(FUZZ_CC) $(CFLAGS) -I$(SRC_DIR) -fsanitize=thread -g -O1 \
$(SRC_DIR)/test_phase$$p.c $(FUZZ_RT) -o $(BIN_DIR)/tsan_phase$$p $(LDFLAGS); \
done
@rc=0; \
out1=$$(SW_QUIET=1 TSAN_OPTIONS="suppressions=tests/stress/tsan.supp" \
timeout 300 $(BIN_DIR)/tsan_msg 4000 2>&1) || rc=1; \
echo "$$out1" | grep -q "WARNING: ThreadSanitizer" && { echo "$$out1" | head -40; rc=1; }; \
out2=$$(SW_QUIET=1 SW_SPIN_US=30 TSAN_OPTIONS="suppressions=tests/stress/tsan.supp" \
timeout 300 $(BIN_DIR)/tsan_msg 4000 2>&1) || rc=1; \
echo "$$out2" | grep -q "WARNING: ThreadSanitizer" && { echo "$$out2" | head -40; rc=1; }; \
out3=$$(SW_QUIET=1 TSAN_OPTIONS="suppressions=tests/stress/tsan.supp" \
timeout 300 $(BIN_DIR)/tsan_storm 2>&1) || rc=1; \
echo "$$out3" | grep -q "WARNING: ThreadSanitizer" && { echo "$$out3" | head -40; rc=1; }; \
for p in 2 4 5; do \
outp=$$(SW_QUIET=1 TSAN_OPTIONS="suppressions=tests/stress/tsan.supp" \
timeout 300 $(BIN_DIR)/tsan_phase$$p 2>&1) || rc=1; \
echo "$$outp" | grep -q "WARNING: ThreadSanitizer" && { echo "phase$$p:"; echo "$$outp" | grep -A6 WARNING | head -28; rc=1; }; \
done; \
rm -f $(BIN_DIR)/tsan_phase2 $(BIN_DIR)/tsan_phase4 $(BIN_DIR)/tsan_phase5; \
[ $$rc -eq 0 ] && echo "tsan-gate: PASS (no unsuppressed races: msg, msg+spin, storm, phase 2/4/5)" \
|| { echo "tsan-gate: FAIL"; exit 1; }
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ needed.
| Var | Default | Effect |
|---|---|---|
| `SW_SCHEDULERS` | CPU count | Number of scheduler threads. `1` for deterministic CLI tools. |
| `SW_MAX_PROCS` | `100000` | Arena ceiling. Drop to `1024`/`4096` for fast-start CLI binaries — saves ~20 ms boot. Floor of 16. |
| `SW_MAX_PROCS` | `100000` | Arena ceiling. Drop to `1024`/`4096` for fast-start CLI binaries — measured ~6 ms total wall (vs ~40 ms at the default ceiling) on Linux x86_64. Floor of 16. |
| `SW_QUIET` | unset | Suppress the `[SwarmRT] Arena initialized…` banner on stderr. Set in scripts/CI. |

---
Expand Down Expand Up @@ -305,7 +305,7 @@ The [`lib/`](lib/) directory ships modules that auto-resolve via `import` — no

| Module | What it gives you |
|---|---|
| `Std` | List / map / string helpers (range, take, drop, nth/at, zip, partition, sort, unique, find, any, all, sum, product, group_by, chunk_every, intersperse, …) — see `lib/Std.sw` for the full list. |
| `Std` | List / map / string helpers (map, filter, join, range, take, drop, nth/at, zip, partition, sort, unique, find, any, all, sum, product, group_by, chunk_every, intersperse, string_join, …) — see `lib/Std.sw` for the full list. `map`/`filter`/`reduce` also exist as global builtins; `Std.map`/`Std.filter`/`Std.join` work too. |
| `Mcp` | Model Context Protocol client + server (JSON-RPC over stdio) |
| `Embed` | Embeddings client for any OpenAI-compatible `/v1/embeddings` endpoint |
| `Vec` | ETS-backed cosine-similarity vector store (`Vec.new / add / search / size`) |
Expand Down Expand Up @@ -351,7 +351,7 @@ make test-full # the comprehensive gate: core + OTP + phases 2-10 + search
- **Compiled** — each `test_*.sw` is compiled with `swc build` and the resulting binary is run.
- **Interpreter** — `tests/sw/repl/test_*.sw` files are run via `swc test` (tree-walking interpreter). Guards against the REPL/codegen builtin drift that the May 2026 marathon closed.

Together the suite reports `all sw tests passed — 53 files, 475 assertions`.
Together the suite reports `all sw tests passed — 56 files, 493 assertions`, and `make test-sw` then runs the **dual-path conformance gate**: every program in `tests/sw/conform/` executes under BOTH `swc run` (interpreter) and `swc build` (compiled) and must produce byte-identical stdout and exit codes — the structural guard against the two paths drifting apart.

Add a `test_<topic>.sw` file in either directory and it'll be picked up automatically.

Expand Down Expand Up @@ -428,7 +428,7 @@ Stable enough to be the substrate for [swarm-code](https://github.com/skyblanket
**What CI gates on, every push:**
- README quickstart (`counter.sw`) + a few more example programs (`hello.sw`, `lambda.sw`)
- `bash scripts/check_sw_docs.sh` — **doc-compile tripwire**: every complete ```sw block in the docs and every runnable `examples/*.sw` must still compile with this `swc`
- `make test-sw` — **53 files, 475 assertions** (`.sw` language: compiled + interpreter + `swc run` paths)
- `make test-sw` — **56 files, 493 assertions** (`.sw` language: compiled + interpreter + `swc run` paths) **plus the dual-path conformance gate** (`tests/sw/conform/` — interpreter and compiled output must be byte-identical per program)
- `make test-phase$p` for `p` in **2 through 10** — C-side runtime tests: GenServer/Supervisor (phase 2), ETS (phase 3), Agent/App/DynSup (phase 4), StateMachine/ProcessGroup (phase 5), TCP (phase 6), hot reload (phase 7), GC scaffolding (phase 8), distribution (phase 9), language frontend (phase 10); the **deadlock watchdog** runs automatically in every test (active by default in the runtime)
- `make stress` — high-process-count race guard (multi-scheduler + single-scheduler spawn storm); every run must complete
- `make gc-stress` — GC v1 copy-on-escape correctness: the value-arena stress harness compiled with ASAN + `-DSW_ARENA_POISON`; a missed deep-copy on any send/spawn/ETS boundary surfaces as a use-after-free or a `0xDE`-garbage content assert
Expand Down
Loading