Embed API: a host thread that attaches to a state, evaluates, and detaches frees its intern table — names it interned (dict keys AND global env bindings, builtins included) dangle for every other thread of that state
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 35/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- c
- Domain
- compilers, documentation, testing-qa
Research direction
Start with docs/EMBEDDING.md and the cited intern-table paths in src/eigenscript.c, then trace attach, detach, and evaluation through src/eigs_embed.c. Reproduce the lifetime failure with the reported scratchpad harness and add the attach/eval/detach/attach-again case to src/embed_concurrent.c. Done means state-owned names remain usable across host-thread detach and reattach without sanitizer errors.
Written by the indexing model from the issue text.
Description
Found by a blind critic during the #1141 review. Pre-existing on main b87bb25; NOT fixed by #1141, whose re-homing is gated on the per-state spawn flag (state->multithreaded), which this shape never sets.
The shape (documented in docs/EMBEDDING.md)
"Inside a state, multiple OS threads can attach (one EigsThread each) and share the state's global env … eigs_thread_detach is called from the same thread before … the thread exits." No spawn is involved, so multithreaded stays 0 and every thread interns names into ITS OWN table (eigs_current->intern_tbl), which eigs_thread_detach → eigs_thread_drain_caches → env_intern_table_unref frees.
Repro (C harness against the ASan objects; scratchpad/host_multiattach.c in the critic's report)
T1: attach, init runtime, eval d is {"pre": 1} and d.from_t1 is 42, detach. T2: attach, eval str of (1 + 2), then keys of d.
==2072370==ERROR: AddressSanitizer: heap-use-after-free ... READ of size 1 thread T2
#0 strcmp #1 env_hash_find src/eigenscript.c:2729 #2 env_get_hashed :4331 #3 env_get
#4 compile_ast src/compiler.c:4000 #5 eval_source src/eigs_embed.c:167 #6 eigs_eval_string
freed by thread T1: #1 env_intern_table_unref src/eigenscript.c:1545
Release build: T2 gets Error line 1: undefined variable 'str' and every read of d returns null. Same result when the SAME OS thread detaches and re-attaches. Identical on b87bb25 and on the #1141 branch.
Why it is wider than dict keys
The global env's names[] — every builtin registered by T1 during init — lives in T1's table. After T1 detaches, the state is unusable from any thread. #1141 closed the dict-key half for the spawn shape only; this is the same lifetime bug one level up, for the host-thread shape.
Fix direction
The intern-table lifetime must be the STATE's, not the thread's, for any name that lands in state-owned structures (global env bindings, module envs, dict keys). Options: the state holds a reference on every attached thread's table (the #1065 chunk-refcount shape, generalised), or the global env re-homes its names into the state-owned table at detach, or interning for state-owned structures always goes to a state-level table and per-thread tables serve only thread-local scratch. Whichever: docs/EMBEDDING.md's multi-attach paragraph becomes true, and src/embed_concurrent.c gains the attach/eval/detach/attach-again case (it does not have one — that is why this was never seen).
Relation to #1141's docs
The #1141 branch scopes its CONCURRENCY.md guarantee to "once the program has spawned" and points here for the host-thread shape.
- Dominant language
- C
- Stars
- 3
- Forks
- 7
- Avg merge
- 4h 15m
- Merged PRs (30d)
- 106
Getting set up
Starts the project's dev container in your browser, under your own GitHub account.
- Ships a Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from InauguralSystems/EigenScript
-
area:lint-tooling bug
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
InauguralSystems/EigenScript#1340 ·
Maintainers usually reply within 1 day
-
area:stdlib found-by:code-review kind:silent-wrong
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
InauguralSystems/EigenScript#1338 ·
Maintainers usually reply within 1 day
-
area:lint-tooling found-by:critic kind:docs-drift
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
InauguralSystems/EigenScript#1335 ·
Maintainers usually reply within 1 day
-
area:ci found-by:critic kind:gate-defect
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
InauguralSystems/EigenScript#1311 ·
Maintainers usually reply within 1 day
-
enrolment: decide test_gc_runner_controls.py (exempt vs enrol) and whether floors need a ratchetOpenarea:gates found-by:critic kind:decision
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
InauguralSystems/EigenScript#1280 · 1 comment ·
Maintainers usually reply within 1 day
All issues in InauguralSystems/EigenScript
Similar issues
-
Difficulty 1/5 Under an hour Newbie friendliness 92/100
sandialabs/seacas#945 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
ARM-software/sysarch-acs#556 · 1 comment ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
bug needs triage
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
netdata/netdata#24062 · 1 comment ·
Maintainers usually reply within 1 day