ReviewOS

zig-utils/zig-js

Runtime: publish environment bindings only after owned-key allocation

#636
Closed chris opened this 9 days ago ·
9 days ago

Problem

The Linux heap-limit failure behind #628/#634 reaches Environment.put after vars.getOrPut has published a new map entry but before dupeBindingName can allocate its owned key. On OOM, the entry temporarily points at parser/source storage and its value slot is not initialized by put.

That ordering violates the engine’s fail-closed allocation contract. A caught allocation failure or later Environment finalization must never observe/free a partially published binding entry. The same get-or-put-then-duplicate pattern exists in the const, global-lexical, function-name, deletable-binding, and module-alias side tables.

Required implementation

  • Allocate owned binding keys before publishing new Environment map entries.
  • On bucket/capacity failure, free every unpublished owned key and leave the map unchanged.
  • Make multi-table operations such as putConst and putAlias transactional: either all required key/value storage is ready or no new semantic state is visible.
  • Preserve existing in-place updates, write barriers, const/function-name semantics, aliases, locking, GC name-byte accounting, and no-GIL publication ordering.
  • Do not swallow OOM, retain source-backed keys, or special-case the failing test.

Acceptance

  • Fault-injection tests fail each owned-key/bucket allocation position and verify unchanged maps, exact live-name accounting, and leak-free finalization.
  • A caught OOM cannot expose an uninitialized/mutable partial declaration or alias.
  • Existing Environment, module binding, heap-limit, full unit, and TSan tests pass.

Roadmap parent: #480 Related: #628, #634, #100, #629

9 days ago

00f9493f makes Environment key ownership and multi-table publication transactional, preserves the private-activation single handshake, and releases DeleteBinding side-table keys exactly. Environment tests pass 10/10 normal and TSan, allocation-failure injection is leak-free, exact shard 0 passes 436/436, and the four affected Test262 subtrees remain 1,058 pass, 0 fail. Fresh Linux CI is pending.

9 days ago

The Linux recovery witness failure in unit shard 1 occurred while allocating the per-iteration lexical loop-control key, before the body-level try that scores Object publication. fc203490 predeclares that test-only counter with var, leaving the 4 MiB cap and every torn/publication/OOM assertion intact. The dedicated binding fault-injection coverage from #636 still exercises transactional key ownership directly. The focused recovery witness passes normally and under TSan with zero leaks; keeping this issue open for fresh Linux confirmation.

9 days ago

Fresh Linux run 32388315489 passed the normal recovery witness, but TSan unit shard 2 exhausted every one of the 500 post-recovery attempts (made == 0) under competing shard load. There was no torn publication and no leak, but this does not satisfy the unchanged acceptance oracle, so I am keeping the issue open. The exact unchanged TSan witness passes locally 3/3 at 12.5–13.9 s on current main. Fresh Linux validation for c6dcbe6d is pending; the 4 MiB cap and success requirements remain unchanged.

9 days ago

Acceptance is complete. Transactional Environment key publication remains covered by its allocation-failure matrix and exact Test262 accounting, and the final bounded publication oracle now passes fresh Linux normal shard 3 and TSan shard 3 with zero leaks. #657 corrected the platform-dependent stale-native-frame assumption without weakening the 4 MiB cap or success oracle.

Sign in to comment on this issue.