33 lines
4.9 KiB
Markdown
33 lines
4.9 KiB
Markdown
# 独立复审P2实施裁决(生产修改前)
|
||
|
||
2026-09-22,依据独立报告《最小登录独立复审-2026-09-22.md》及 ReviewLifecycleTests/regression-failing.log,实际方法提取的4条退出安全断言失败,正常对照4条通过。非Unity竞态复现,不把历史快速换号0错误扩大为全时序安全。
|
||
|
||
## 完整方案与边界
|
||
|
||
仅修改三个生产文件:
|
||
|
||
1. FishingAct.cs:GetUI与同一首登分支NewEnterMap,在入口捕获原container及IUserService.LoginLifetime;每个await后先检查Unity对象销毁、令牌取消或container替换,失效立即返回。所有后续Resolve使用原container。已有正常UI流程和补单调用保持,不改奖励/玩法。新手分支同样保留正常行为,不扩大到其他玩法异步方法。
|
||
2. SoundService.cs:新增私有初始化版本号,InitAsync开始递增并捕获;Release首先递增使在途Init失效。两个Addressables句柄由局部变量持有,await后先检查版本;仅完整有效初始化时将局部句柄移交成员。try/finally在未移交时释放本次局部有效句柄;Release只释放成员,避免双释放/误释放后一次初始化资源。旧等待返回不再注册lowpass事件、建池;接口和调用方签名不变。
|
||
3. SoundMgr.cs:新增私有初始化版本号;Release先递增。Init捕获原container,每个等待返回检查版本和container。residentFish按地址去重加载(已有数组首项重复,否则opMap覆盖句柄造成漏释放);局部opMap由try/finally负责,仅有效完成时移交residentClip,未移交则释放每个有效句柄。保持成功后已有按clip释放机制,不改音量/音效/播放规则。旧完成不得注册全局订阅、写音量或解析新container。
|
||
|
||
## 资源/错误策略评审
|
||
|
||
- 采用局部句柄+移交标志,Release不会处理尚未移交的句柄;在途方法finally负责其本次句柄,释放恰好一次。SoundMgr取消轮询时可释放未完成句柄,之后不再读取结果;SoundService等待完成后释放,不制造取消异常。
|
||
- 同一实例后续Init通过新版本与旧任务隔离;不新增自动重试、吞正常加载异常或全局catch。原有效初始化仍传播资源失败。初始化/退出都沿Unity主线程,不引入并行修改容器。
|
||
- 正常完成的音频资源沿原Release路径,定向测试必须覆盖正常Init/Release与重复Release,不能仅证明旧回调被跳过。
|
||
- Config、身份、存档、KV、俱乐部、SDK、服务器及预编译框架不在边界。修改前已Stop C盘Play,D盘不动。
|
||
|
||
## 验证计划与裁决
|
||
|
||
重新提取上述真实方法,保留失败基线;验证GetUI各等待点退出/换容器,声音两级初始化等待中Release、重复释放、正常初始化与新实例初始化。然后Unity编译、Play实际101→102→101和实际Hub/错误日志复查,独立agent复审本次差异。无法确定性覆盖的Unity细粒度资源时序明确保留证据限制。
|
||
|
||
主会话完整方案评审结论:上述最小边界可实施;已复现问题满足用户“发现问题再编码修复”的条件,不需扩大范围。独立agent的详细方案作为补充审查,不替代本裁决;若发现资源归属反例,先更新裁决再改。
|
||
|
||
## 独立方案补充评审裁决(完善实现前)
|
||
已完整读取《独立复审P2修复方案-2026-09-22.md》,认可失败回滚与重复Init资源条件。补充允许FishingAct.OnCameraSpeedEvent这一NewEnterMap直接子方法:在其自身等待后检查同一对象/令牌/容器,避免外层检查过晚;不改相机时序。GetUI/NewEnterMap入口拒绝已销毁对象。
|
||
SoundService/SoundMgr成功Init后的再次Init先释放已移交成员;新一代失效旧等待。初始化订阅用局部变量持有,只有全部成功才移交成员;当前初始化失败由Release清理本实例已初始化部分,局部finally释放未移交资源/订阅,旧版本失败不触及新版本。正常资源失败继续抛出。此补充与独立评审条件一致,可实施并做资源引用逐个断言。
|
||
|
||
## Unity复现后的第四文件补充裁决(实施前)
|
||
快速101→102实际复跑在FishingStage.StartAsync:191发生AddTo空container,p2-progress-102-errors.json。Stop已将disposable置null,但Unity对象尚未销毁、QuitAct尚未注销,原this/token检查不能识别“已Stop但仍活”的阶段。不能通过新建订阅容器让旧阶段继续运行。
|
||
允许仅增加FishingStage.cs:私有stopping标识在Stop入口(任何清理前)设true,OnDestroy也设true;Start入口、现有每await/进度回调和旧初始化异常过滤加入该条件。disposable释放改可空以支持重复Stop清理。保持正常启动行为、错误传播和既有场景顺序,不改框架DLL。独立review/test补stopped-alive-uncancelled分支,真实快速流程重新跑;失败证据存档。本补充由主会话完整评审通过,生产边界更新为四文件。
|