Repository navigation
fix(events): Node 保持不可重入,快速路径上的 emit 排在被扣住的同名调用之后;等待图记入口,修复可重入运行时上查不出的卡死 - #527
Merged
Merged
Conversation
- Node 保持不可重入:emit 方式的 events.call 在同步等待期间照旧被扣住;会话新增 behind,本进程快速路径上的同名 emit 排在被扣住的调用之后,按帧的顺序执行(§5.5) - 等待图:没有调用方同步等待、进入 sync-stack 运行时的调用记为入口,栈顺序对它成立;修复可重入的 Python / Bun 把监听器压在等待上面、回调不可重入运行时时查不出的卡死 - TLA+ 模型加入 Rust 的投递(入口),新增 current-posts 等四个配置 - 测试:Node 会话单元测试、waits 单元测试、sync_cycles 集成测试(Python / Node / Bun) - 文档:§5.5 撤回 Node 对监听器可重入的说法;迁移说明、运行时约定、多语言设计 §9、保证表
eric8810
force-pushed
the
fix/node-emit-hold-order
branch
from
October 21, 2026 12:46
a8941e1 to
004ff43
Compare
This was referenced Oct 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#520 的故障评审发现的回退(阻塞 0.15):#520 让 Node 在同步等待期间就地执行 emit 方式的
events.call,Node 因此变得可重入,带来两个问题。SyncWaitCycle。修正
Node 保持不可重入,§5.5 照样成立
session.mjs/runner.mjs的改动:同步等待期间,emit 方式的events.call和其他不在等待链上的调用一样被扣住,等待结束后按帧的顺序执行。behind(key, run)和选项holds:运行时把 emit 方式的events.call标上事件名。总线在快速路径上发出emit时,如果同名的调用还被扣着没执行,就把这次本地分发排在它们后面(#queued里的一项,等待期间同样扣住)。所以emit/order-across-fast-path-sync-wait仍是 a:1 先于 a:2,并且走快速路径(viaHost: false)。Bun / Python:同样的卡死确实存在,已修正
它们按设计在同步等待期间执行所有调用,并声明
reentrant-sync与sync-stack。但宿主的等待图只记录“为同步等待的调用方转发的调用”。宿主自己发出的events.call(以及任何异步调用)不在图里,所以监听器被压在 x 上面这件事,栈顺序那类边看不到。集成测试在 main 上对 Python、Bun 都会卡住(10 s 超时)。waits.rs:有调用被标记时,没有调用方同步等待、又进入sync-stack运行时的调用,记为入口。栈顺序对入口成立:c 等在它之后进入、并已开始执行的入口。入口等它之下发出的同步调用。没有谁按调用链等入口,因为它的调用方不等它。这样上面的环 c.y → x → 入口 → c.y 能被查到,回调得到SyncWaitCycle,其余照常完成。TLA+ 模型(
specs/cross-runtime-sync)加入 Rust 的投递(MaxPosts、posts,即入口),TrueSucc/RustSucc把入口算进图。新增三个配置:current-posts:卡死(反例 5)policy-b-posts:通过(253,235 个状态);不记入口时,同一配置在策略 B 下卡死policy-b-posts-node:p 不可重入(Node),通过(152,438 个状态)已有配置加
MaxPosts = 0。本地用 tla2tools v1.7.4(sha256 与 README 一致)跑了全部配置,结果都与expected.txt一致,通过的配置状态数不变。测试
node/rutis-runtime/test/session.test.mjs:同步等待期间 emit 方式的调用不在等待上面执行(监听器看到的是完成后的状态,回复顺序正确);behind按帧的顺序排在被扣住的同名调用之后,没有被扣住的调用时由调用方直接执行。waits.rs::tests::a_listener_run_on_top_of_a_wait:可重入时成环;不可重入时不成环;没有谁按调用链等入口。crates/rutis-loader/tests/sync_cycles.rs::an_emit_listener_run_while_a_call_waits,A 分别是:SyncWaitCycle,其余完成;已核实:在 main 上 Python、Bun 卡住;用 fix(events): Node 按帧序就地开始 emit 方式的监听器调用,补同步等待用例、回复原语测试与文档 #520 的 Node 代码时,Node 那一项的断言失败。
一致性套件:
emit/order*在 node、node-leaf 两列(全部摆放)通过;整套(sampled)见下方 CI。文档
runtime-contract.md:同上。bridge/sync-wait-cycle-refused补两个测试。