Skip to content

Commit 8143fd2

Browse files
authored
Merge branch 'dev' into CI/NSIS
2 parents 9a40977 + 279bb6b commit 8143fd2

184 files changed

Lines changed: 12180 additions & 1831 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
---
2+
name: windows-dmp-analysis
3+
description: 分析 Windows 崩溃转储文件(.dmp),诊断 MaaNTE 及其依赖项(MaaFramework、MXU)的崩溃。自动从 GitHub Releases 下载对应版本 PDB 符号,使用 minidump-stackwalk 解析堆栈轨迹并定位崩溃根因。当 issue 日志包或附件中发现 .dmp 文件,或用户要求分析 DMP/崩溃转储时使用。
4+
---
5+
6+
# Windows DMP Analysis
7+
8+
## Scope
9+
10+
- Windows minidump (.dmp) files from MaaNTE.
11+
- MaaNTE crashes almost always originate in **MaaFramework** (C++) or **MXU** (Rust/Tauri), not MaaNTE's Python code.
12+
- Only x86_64 covered below; for aarch64, substitute `x86_64``aarch64` in all download URLs.
13+
14+
## Prerequisites
15+
16+
在本仓库的 CI workflow 中会安装并确保 `minidump-stackwalk``dump_syms` 可用。如果你在本地复现或手动运行本流程,需要自行安装这些工具:
17+
18+
```bash
19+
which minidump-stackwalk && which dump_syms
20+
```
21+
22+
If either is missing, install via:
23+
24+
```bash
25+
curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
26+
cargo binstall -y --no-confirm minidump-stackwalk dump_syms
27+
```
28+
29+
## Workflow
30+
31+
### 1. Obtain DMP
32+
33+
Download `.dmp` to `.cache/dmp-analysis/issue-<number>/`.
34+
35+
Sources:
36+
37+
- Direct issue attachment (image/file link ending in `.dmp`)
38+
- Inside `MaaNTE-logs-*.zip` log package
39+
40+
```bash
41+
WORK=".cache/dmp-analysis/issue-<NUMBER>"
42+
mkdir -p "$WORK"
43+
curl -L "<dmp_url>" -o "$WORK/crash.dmp"
44+
```
45+
46+
### 2. Quick unsymbolicated analysis
47+
48+
```bash
49+
minidump-stackwalk "$WORK/crash.dmp" 2>/dev/null
50+
```
51+
52+
This gives without any symbols: OS info, exception type, module list with versions, raw stack frames.
53+
54+
Identify the **crashing module** from the exception address or the top stack frame.
55+
56+
### 3. Determine dependency versions
57+
58+
DMP module version info is frequently empty/unavailable. Prefer log and config sources:
59+
60+
| Priority | Source | How |
61+
| -------- | ------ | --- |
62+
| 1 | MXU logs | `maa_init success, version: v5.x.x` |
63+
| 2 | Agent logs | `PI_CLIENT_MAAFW_VERSION` in PI environment log |
64+
| 3 | Config files from logs package | `interface.json`, config files |
65+
| 4 | Issue text | User-reported version |
66+
| 5 | Module list in stackwalk output | Version column (often shows `?`) |
67+
68+
Record:
69+
70+
- **MaaFramework version** (e.g. `5.9.2`)
71+
- **MXU version** (e.g. `1.21.2`)
72+
73+
### 4. Download PDB symbols
74+
75+
#### MaaFramework
76+
77+
```bash
78+
MAA_VER="<version>" # e.g. 5.9.2
79+
curl -sL "https://github.com/MaaXYZ/MaaFramework/releases/download/v${MAA_VER}/MAA-win-x86_64-v${MAA_VER}.zip" \
80+
-o "$WORK/maa-fw.zip"
81+
unzip -joq "$WORK/maa-fw.zip" 'symbol/*.pdb' -d "$WORK/pdb/"
82+
```
83+
84+
PDB files inside `symbol/`:
85+
86+
| PDB | Corresponding Module |
87+
| --- | -------------------- |
88+
| MaaFramework.pdb | MaaFramework.dll — core pipeline runtime |
89+
| MaaUtils.pdb | MaaUtils.dll — utility library |
90+
| MaaToolkit.pdb | MaaToolkit.dll — toolkit |
91+
| MaaWin32ControlUnit.pdb | MaaWin32ControlUnit.dll — Win32 controller |
92+
| MaaAdbControlUnit.pdb | MaaAdbControlUnit.dll — ADB controller |
93+
| MaaAgentServer.pdb | MaaAgentServer.dll — agent server |
94+
| MaaAgentClient.pdb | MaaAgentClient.dll — agent client |
95+
| MaaPiCli.pdb | MaaPiCli.exe — CLI entry |
96+
97+
#### MXU
98+
99+
```bash
100+
MXU_VER="<version>" # e.g. 1.21.2
101+
curl -sL "https://github.com/MistEO/MXU/releases/download/v${MXU_VER}/MXU-win-x86_64-v${MXU_VER}.zip" \
102+
-o "$WORK/mxu.zip"
103+
unzip -joq "$WORK/mxu.zip" 'mxu.pdb' -d "$WORK/pdb/"
104+
```
105+
106+
### 5. Convert PDB → Breakpad .sym
107+
108+
```bash
109+
mkdir -p "$WORK/symbols"
110+
for pdb in "$WORK/pdb/"*.pdb; do
111+
name=$(basename "$pdb" .pdb)
112+
header=$(dump_syms "$pdb" 2>/dev/null | head -1)
113+
debug_id=$(echo "$header" | awk '{print $4}')
114+
dest="$WORK/symbols/${name}.pdb/${debug_id}"
115+
mkdir -p "$dest"
116+
dump_syms "$pdb" > "$dest/${name}.sym" 2>/dev/null
117+
done
118+
```
119+
120+
### 6. Full symbolicated stack walk
121+
122+
```bash
123+
minidump-stackwalk "$WORK/crash.dmp" "$WORK/symbols" 2>/dev/null
124+
```
125+
126+
### 7. Analyze results
127+
128+
#### What to focus on
129+
130+
1. **Crashing thread** — read stack top-down.
131+
2. **Exception type**:
132+
- `EXCEPTION_ACCESS_VIOLATION` (0xC0000005) — null/dangling pointer, use-after-free
133+
- `EXCEPTION_STACK_OVERFLOW` (0xC00000FD) — infinite recursion or oversized stack allocation
134+
- `EXCEPTION_ILLEGAL_INSTRUCTION` (0xC000001D) — corrupted code or wrong CPU feature
135+
- `STATUS_STACK_BUFFER_OVERRUN` (0xC0000409) — **NOT always a real buffer overrun.** Check the first exception parameter:
136+
- `0x7` = `FAST_FAIL_FATAL_APP_EXIT``std::terminate()` / `abort()` was called, typically from an **unhandled C++ exception** (e.g. `cv::Exception` from OpenCV). This is the most common crash pattern.
137+
- `0x2` = `FAST_FAIL_RANGE_CHECK_FAILURE`
138+
- Other values: see [FAST_FAIL codes](https://learn.microsoft.com/en-us/windows/win32/debug/fast-fail-constants)
139+
- `EXCEPTION_BREAKPOINT` (0x80000003) — deliberate crash / assertion failure / Rust panic
140+
3. **Faulting module ownership**:
141+
- `Maa*.dll` → MaaFramework → upstream `MaaXYZ/MaaFramework`
142+
- `mxu.exe` → MXU → upstream `MistEO/MXU`
143+
- `onnxruntime_maa.dll`, `opencv_world4_maa.dll` → third-party inference/vision
144+
- `DirectML.dll` → DirectX ML runtime
145+
- `ntdll.dll`, `KERNELBASE.dll`, `ucrtbase.dll` → OS / CRT; look at the caller frames above
146+
- If crash address is in `ucrtbase.dll` with code 0xC0000409, the real crash site is in the **caller frames**, not ucrtbase itself
147+
148+
### 8. Cross-reference with source
149+
150+
If the crash is in MaaFramework:
151+
152+
```bash
153+
git clone --depth 1 --branch "v${MAA_VER}" \
154+
https://github.com/MaaXYZ/MaaFramework.git ".cache/upstream-src/MaaFramework"
155+
```
156+
157+
If the crash is in MXU:
158+
159+
```bash
160+
git clone --depth 1 --branch "v${MXU_VER}" \
161+
https://github.com/MistEO/MXU.git ".cache/upstream-src/MXU"
162+
```
163+
164+
Look up the function and line from the symbolicated stack trace in the cloned source.
165+
166+
## Output Format
167+
168+
```markdown
169+
## DMP 分析结果
170+
171+
- DMP 文件:`<filename>`
172+
- 操作系统:`<OS version>`
173+
- 异常类型:`<EXCEPTION_*>`
174+
- 崩溃模块:`<module_name>` (版本 `<version>`)
175+
- 崩溃函数:`<symbolicated function name>`
176+
177+
## DMP 崩溃分析
178+
179+
### 崩溃堆栈(crashing thread)
180+
181+
<crashing thread 的全部有效符号化堆栈帧>
182+
183+
### 关键模块版本
184+
185+
| Module | Version |
186+
| ---------------- | ------- |
187+
| mxu.exe | ... |
188+
| MaaFramework.dll | ... |
189+
| ... | ... |
190+
191+
### 根因判断
192+
193+
- 崩溃归属:MaaFramework / MXU / 第三方依赖 / 未知
194+
- 分析:...
195+
- 置信度:高 / 中 / 低
196+
197+
### 建议
198+
199+
- 对用户的建议(升级、绕过方案等)
200+
- 对开发者的建议(上游报告、修复方向)
201+
```
202+
203+
## Cleanup
204+
205+
After analysis is complete:
206+
207+
```bash
208+
rm -rf ".cache/dmp-analysis/issue-<NUMBER>"
209+
```
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
---
2+
name: maa-logging
3+
description: MaaNTE Python 日志规范。覆盖 agent/utils/logger.py 的 loguru/标准 logging 使用方式、日志级别选择、格式化与最佳实践。在编写或修改 agent/ 下的 Python 代码、添加日志输出、或审查日志质量时使用。
4+
---
5+
6+
# MaaNTE Python 日志规范
7+
8+
## 架构
9+
10+
MaaNTE 的日志系统位于 `agent/utils/logger.py`,提供统一的 `logger` 对象:
11+
12+
- **优先 loguru**:若已安装 `loguru`,则使用 loguru 的彩色输出与结构化日志。
13+
- **回退标准 logging**:若未安装 loguru,使用标准库 `logging` + `TimedRotatingFileHandler`
14+
- **控制台**:根据客户端类型(MXU / MFAAvalonia / 其他)自动适配输出格式(HTML 彩色 / 短标签 / ANSI 颜色)。
15+
- **MXU 模式**:console_level 自动降为 `"WARNING"`,用户只看到 WARNING/ERROR;INFO/DEBUG 仅入文件日志。
16+
- **文件**:按天滚动,保留 2 周,压缩归档;文件日志固定带时间戳和调用位置。
17+
18+
## logger 与 maafocus 的职责分离
19+
20+
```
21+
logger → 开发者日志(内部状态、算法细节、调试信息)
22+
maafocus → 用户可见消息(任务进度、状态变更、错误提示)
23+
```
24+
25+
- `logger.debug/info` 在 MXU 模式下**不会**出现在用户面前(console_level = WARNING)。
26+
- 所有面向用户的消息必须使用 `maafocus.Print(context, msg)``maafocus.PrintT(context, key, *args)`
27+
- `maafocus.PrintT()` 自动通过 `utils.i18n.T()` 查翻译,支持多语言。
28+
- 详见 [python-action-guide](../python-action-guide/SKILL.md#用户可见消息maafocus)
29+
30+
## 导入
31+
32+
```python
33+
from utils.logger import logger
34+
```
35+
36+
如果模块在 `custom/action/` 下且 `utils` 不在直接路径中,参考已有代码的相对导入方式。少数子模块(如 `SoundDodgeAction.py`)通过 `custom.action.Common.logger.get_logger(__name__)` 获取独立 logger,这是为了利用 loguru 的 `{name}` 字段;若不关心区分 logger 名,直接用 `from utils.logger import logger` 即可。
37+
38+
## 日志级别
39+
40+
| 级别 | 用途 | 示例 |
41+
|------|------|------|
42+
| `logger.info` | 内部关键步骤、启动初始化 | `logger.info("已加载演奏配置文件: %s", path)` |
43+
| `logger.debug` | 识别细节、中间计算结果 | `logger.debug("未识别到 %s", name)` |
44+
| `logger.warning` | 可恢复异常、降级、配置缺失 | `logger.warning("鼓面模板缺失,演奏检测不可用")` |
45+
| `logger.error` | 不可恢复错误 | `logger.error("Error: %s", e)` |
46+
| `logger.success` | 操作成功确认(loguru) | `logger.success("初始化完成")` |
47+
| `logger.trace` | 逐帧/高频细节(loguru) | `logger.trace("候选入队: ...")` |
48+
49+
**注意**:MXU 模式下 console_level 为 `"WARNING"``logger.info` 不会出现在用户面前。用户可见的消息请用 `maafocus.PrintT()`
50+
51+
## 格式化
52+
53+
使用 `%s` / `%d``%` 风格占位符(loguru 风格),不要手动拼接字符串:
54+
55+
```python
56+
# Good
57+
logger.info("演奏开始 | FPS=%d | 鼓面检测=%s", target_fps, drum_available)
58+
logger.debug("未识别到 %s", name)
59+
logger.warning("候选丢弃: lane=%s target=%.3f reason=min_interval", lane, target_time)
60+
61+
# Bad
62+
logger.info("演奏开始 | FPS=" + str(target_fps))
63+
logger.info(f"演奏开始 | FPS={target_fps}")
64+
```
65+
66+
## 禁止 print / logger.info 用户消息
67+
68+
**用户可见的消息必须通过 `maafocus.Print()` / `PrintT()` 发送,禁止 `print()``logger.info()`**
69+
70+
```python
71+
# Bad — 用户看不到(MXU 模式下 logger.info 被过滤)
72+
logger.info("冲咖啡任务开始")
73+
print("=== Auto Make Coffee Action Started ===")
74+
75+
# Good — 用户能看的用 maafocus
76+
PrintT(context, "coffee.started")
77+
PrintT(context, "coffee.making", count + 1, make_count)
78+
79+
# Good — 开发者调试用 logger
80+
logger.debug("识别分数: prob=%.2f", prob)
81+
logger.warning("模板缺失,功能降级")
82+
logger.error("不可恢复错误: %s", e)
83+
```
84+
85+
## 敏感信息
86+
87+
不要在日志中输出密钥、完整文件路径中包含敏感信息的用户名等。
88+
89+
## 审查清单
90+
91+
- [ ] 导入使用 `from utils.logger import logger`(或合理的相对导入)
92+
- [ ] 日志级别合理:info 用于关键节点,debug 用于识别细节
93+
- [ ] 使用 `%` 风格占位符,不拼接字符串、不用 f-string
94+
- [ ]`print()` 调用(应使用 logger 或 pipeline focus)
95+
- [ ] 无高频大量日志(循环内使用 debug/trace)
96+
- [ ] 异常信息包含足够的上下文(参数值、当前步骤)

0 commit comments

Comments
 (0)