Repository navigation
fix(tests): 两个反复出现的偶发失败——rutis-dev 的套接字替换、Windows 上运行时被杀后的重启 - #501
Merged
Merged
Conversation
rutis-dev channel.rs::a_live_socket_is_not_replaced_but_a_stale_one_is: 测试用 std UnixListener 绑定后立即丢弃来造“崩溃留下的旧套接字”。同一测试 进程里 the_cli_keeps_the_row_id 并行地启动 rutis-dev 子进程;子进程在 fork 到 exec 之间持有父进程全部描述符的副本(CLOEXEC 只在 exec 时关闭),被丢弃 的监听套接字在这段时间里仍在监听,connect 成功,DevChannel 判它“仍有人 监听”而报 AddrInUse。产品逻辑没错。改为用 UnixDatagram 绑定造旧套接字:同样 是没人接受连接的套接字文件,但永远不会接受流连接。Linux 容器里循环 300 次: 旧测试失败 14 次,新测试 0 次。 e2e runtime_crash.rs::a_killed_runtime_fails_its_calls_and_a_restart_recovers (Windows):失败与端口无关,是 "process N is not one of M's"。Windows 上 venv 的 python.exe 是启动器,真正的解释器是它的子进程,放在一个 KILL_ON_JOB_CLOSE 的作业里;杀掉启动器,子进程随之结束(反之亦然,启动器在子进程退出后自己 退出)。场景逐个杀 Python 进程,每次重新列一遍主机的进程,第二个可能已经 随第一个结束而不在列表里。Scenario::kill 改为接收一组 pid:一次列举核对全部 属于主机,然后逐个杀;轮到时已经结束的进程(ESRCH;Windows 上进程已不存在或 已有退出码)不算错。runtime_crash 的两个场景与 soak 都改用它,场景意图不变。
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.
问题
crates/rutis-dev/tests/channel.rs::a_live_socket_is_not_replaced_but_a_stale_one_is偶发失败(feat(swift): Swift SDK 的会话层与值(#386) #491、feat(swift): 远程运行时 listen: 与 dial:,一致性的 Swift 列(#387) #496;run 39245891413 / job 118037687992,自托管 Linux):第二次DevChannel::start报a dev channel already listens on /tmp/.tmpXXXX/dev.sock(AddrInUse),路径在测试自己的临时目录里,不是别的测试或别的作业占了路径。tests/e2eruntime_crash.rs::a_killed_runtime_fails_its_calls_and_a_restart_recovers在 Windows 偶发失败(同一 run,job 118037688593)。日志里的 panic 是process 2812 is not one of 16416's(tests/e2e/src/lib.rs的Scenario::kill),发生在杀 Python 运行时这一步,与重启后复用端口无关。根因
std::os::unix::net::UnixListener::bind绑定后立刻丢弃,来造“崩溃留下的旧套接字”。同一测试二进制里the_cli_keeps_the_row_id并行地启动rutis-dev子进程;子进程从 fork 到 exec 之间持有父进程所有描述符的副本(CLOEXEC要到 exec 才关),刚丢弃的监听套接字在这段时间仍在监听,于是connect成功,DevChannel正确地判定“有人在监听”。产品逻辑没有问题,是测试造出的“旧套接字”并不旧。/bin/true,主线程 bind→drop→connect)20000 次中 673 次连上;同样循环改用UnixDatagram为 0 次。python -m venv,venv 的python.exe是启动器,真正的解释器是它的子进程,放在一个JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE的作业里:杀掉启动器,子进程随之被杀;先杀子进程,启动器随后自己退出。所以 Python 运行时在 Windows 上是两个进程。场景逐个调用Scenario::kill,每次重新列举主机的进程并断言目标在其中;第二个进程可能已随第一个结束,断言就失败。是否失败取决于这段时序,所以是偶发的。a_killed_runtime_restarted_on_failure_brings_its_rows_back和 soak 的同一写法有相同的竞争。改法
UnixDatagram::bind造旧套接字(stale_socket辅助函数,注释写明原因):同样是没人接受连接的套接字文件,但永远不会接受流连接,子进程短暂持有副本也不影响。另一个测试里指向旧套接字的符号链接也用它。Scenario::kill(host, pid)改为Scenario::kill(host, &[pid]):一次列举,核对所有 pid 都属于主机,再逐个杀;轮到时已经结束的进程不算错(Unix:ESRCH;Windows:OpenProcess报进程不存在,或TerminateProcess失败但进程已有退出码)。其他错误仍然 panic。runtime_crash.rs两个场景和soak.rs改用它。场景意图不变:仍是kill -9运行时的全部进程、在途调用失败、其余运行时不受影响、主机停后以第一台主机拿到的端口重启。验证
cargo test -p rutis-dev --test channel300 次:改前 14 次失败,改后 0 次。cargo test -p rutis-dev循环 100 次通过;cargo test -p rutis-e2e --no-fail-fast除cordis外全部通过(cordis本机失败是本机 Node 22.13 没有zlib.createZstdCompress,与本改动无关);runtime_crash多次通过。cargo check -p rutis-e2e --tests --target x86_64-pc-windows-msvc通过。runtimes-windows)在本分支手动触发两次,见下方评论。