Repository navigation
fix(everest): 安装器原生崩溃时给出能照做的提示,而不是只甩一段栈 - #94
Open
std-external wants to merge 2 commits into
Open
std-external wants to merge 2 commits into
std-external wants to merge 2 commits into
Conversation
MiniInstaller 有时不是报安装错误,而是直接死在 .NET 运行时自己的原生代码里 (AccessViolationException 打在 relinker 的 String.StartsWith → Globalization P/Invoke 上)。这段栈对用户没有用,还会让人以为游戏或 CeleMod 坏了。 CELEMOD 侧确认过的事实:MiniInstaller 的 StandardMode 是在本进程里单线程调 MonoMod 的(DepCalls.RunMonoMod → MonoModder.AutoPatch),MonoModder 自己没有 任何 Parallel/Task,官方 Everest 也没有并行 relink/并行加载开关(那两个 EVEREST_PARALLEL_* 是 EverestUltra 的),所以这次崩溃不是重链竞态,而是进程里 被别的东西打坏了原生内存/运行时:常见是杀毒软件、显卡驱动的游戏内覆盖层之类 注入到每个进程的东西,或者游戏目录里那份 piton-runtime 被打坏。 安装失败时按栈里的特征串认出这类崩溃,在原始错误后面补一条能照做的建议 (先关实时防护和游戏内覆盖层再装一次;不行就手动解压 Main.zip 跑 MiniInstaller-win64.exe),本地包安装走同一个提示。其他安装失败原样返回。
用户反馈这类崩溃是偶发的:同一台机器、同样的步骤,之前成功过一次。所以它的 性质是「偶发 + 崩在运行时原生层」,不是确定性的环境损坏。 - everest.rs:抽出 extract_everest_archive,安装失败且错误串带原生崩溃特征 (is_installer_native_crash:AccessViolationException / 受保护内存中英文)时, 重新解压一遍再跑一次 MiniInstaller(崩溃那次会把游戏目录留在半装状态,不 重解压直接重跑不安全),只重试一次,两次都崩才把错误抛给用户。 - everest.rs:在 Windows 上给安装器子进程设 DOTNET_SYSTEM_GLOBALIZATION_USENLS=1。 MonoMod 在 FindType 里用文化相关的 String.StartsWith 比依赖名,.NET 在非 en* 区域设置下会走 ICU(dotnet/runtime#132702 是同一个栈,运行时团队判定该路径是 外部堆破坏的最早受害者);让安装器进程用 NLS 只影响这些 ASCII 前缀的比较结果 (完全一致),对子进程来说是安全的默认值。 - backend.rs:提示文案改成「已经自动重装过一遍还是崩」,并把重试放在第一位。 cargo test --lib: 119 passed(新增 3 个:崩溃特征识别、失败后确实重试并成功、连续崩两次不循环)。
Contributor
Author
追加(用户补了关键信息:这条崩溃是偶发的)「同一台机器、同样的步骤之前成功过一次」→ 说明不是确定性的环境损坏,而 CelebrMod 这边能兜的正好是「偶发」:失败自动重试一次。顺带找到了同栈的上游报告。 新增改动(第二个提交)
澄清一点:并行 relink 这条不适用官方 Everest 和 MiniInstaller 里没有 验证
上游情况
|
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.
现象
群里一位用户用 CeleMod 装 Everest 时反复失败,CeleMod 只弹出一整段 .NET 的崩溃栈:
这段栈没有任何可执行的信息,用户只能去问 AI / 搜 B 站(他最后是「更新显卡驱动」装上的)。
不是重链竞态(先说清楚,免得 PR 修错了地方)
MiniInstaller/Program.cs:53StandardMode在本进程里同步调DepCalls.RunMonoMod(:108/:109/:112),DepCalls.RunMonoMod只是AsmMonoMod.EntryPoint.Invoke→MonoModder.AutoPatch;上游MonoModder.cs(MonoModreorganize分支)里没有任何Parallel/Task/ 线程,这条重链路径是单线程的。EVEREST_PARALLEL_RELINK、EVEREST_PARALLEL_LOAD是 EverestUltra 的开关(CeleMod 的is_everest_ultra正是靠EVEREST_PARALLEL_LOAD这个字符串认 EU 的)。安装阶段也不会走到游戏里的加载器。String.StartsWith走到 原生 globalization P/Invoke 才被 AV 打断 —— 托管字符串不会凭空指向受保护内存,这类 AV 说明进程里的原生层已经被打坏了(杀软/驱动覆盖层注入、游戏目录里那份piton-runtime被打坏等),不是 CeleMod 或 Everest 的哪一行逻辑写错。用户「更新显卡驱动后就好了」也符合这一类(换掉的只是注入到每个进程里的东西)。改了什么
src-tauri/src/backend.rs:新增with_installer_crash_hint,在安装失败的错误串里认出这类原生崩溃(System.AccessViolationException/Attempted to read or write protected memory/ 中文运行时的「尝试读取或写入受保护的内存」),在原错误后面补一段能照做的建议:everestapi.github.io下 Everest 的Main.zip,解压到游戏目录,再跑MiniInstaller-win64.exe。接在两处(下载安装 + 本地包安装),沿用已有的
with_file_in_use_hint(#89)的写法;其他安装失败原样返回,不做任何改写。验证
cargo test --lib:116 passed, 0 failed(新增 3 个:英文栈 / 中文栈都会补提示、原始错误保持在最前;正常的安装失败不被改写)。cargo fmt已跑,无额外改动。没做 / 留给后面
piton-runtime:InGameUpdaterHelper只在自己更新(everest-update目录)时才删,CeleMod 的正常安装是一层层覆盖解压。是否要顺手清掉这份运行时值得单独讨论(删早了、解压又失败的话游戏会连运行时都没有),先不动。Mods/Cache、Steam 校验后重装等)——那些已经在给用户的手册里。来源:Celeste Coders 群用户报告。