RTU/mimo/问题处理文档.md

143 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 问题处理文档
---
## 2026-06-15
### #8 libtask 事件/消息队列缺陷修复
**问题**
1. `task_event_destroy``task_msg_queue_destroy``free(p)` 后仍访问 `p->name`use-after-free
2. `task_event_recv` 中 AND 检查用 `opt == TASK_EVENT_FLAG_AND` 而非位测试,`AND | CLEAR` 组合被误识别为 OR
3. `task_event_send``pthread_cond_signal` 而非 `cond_broadcast`,多等待者场景可能唤醒不足
**修复**
1. `free(p)` 移到 `LOG_I` 之后,先打日志再释放
2. `opt ==` 改为 `opt &` 位测试
3. `cond_signal` 改为 `cond_broadcast`
**状态**:✅ 已完成
**涉及文件**`src/public/libtask/src/myTask.c`
**验证**`./release/build.sh` 编译通过
---
### #7 libtask 定时器 SIGEV_THREAD 线程爆炸
**问题**`myTask.c` 使用 `timer_create(CLOCK_REALTIME, SIGEV_THREAD)` 模式每次定时器超时内核创建一个新线程执行回调。9 个 app 线程 × 3 个定时器10ms/100ms/1000ms= 27 个定时器,每秒约 1000 次内核线程创建/销毁,系统开销极大。回调仅做 `task_event_send` 设一个事件位(几微秒),线程创建开销远大于实际工作。
**需求**
1. 消除每次定时器超时创建线程的开销
2. API 签名全部不变,调用方零修改
3. 仅 Linux 平台
**处理计划**[libtask定时器SIGEV_THREAD优化](./plan/libtask定时器SIGEV_THREAD优化.md)
**修复方案**:用 Linux **timerfd** + **epoll** + **单例管理器线程** 替代 `SIGEV_THREAD`
- `stru_task_timer``timer_t timerid` → `int timerfd`,新增 `pthread_cond_t cond`、`int in_epoll`
- 删除 `task_timer_sig_handler`,新增 `timer_manager_thread`epoll_wait 监听所有 timerfd超时时调用原始回调
- `task_timer_stop/destroy``while(running) usleep(1000)` 忙等 → `cond_wait` 零 CPU 阻塞
- 6 个 API 签名全部不变
**状态**:✅ 已完成
**涉及文件**`src/public/libtask/src/myTask.c`(仅此一个文件,`release/inc/myTask.h` 无改动)
**验证**`./release/build.sh` 编译通过,零错误零警告
---
## 2026-06-12
### #6 Tab 补全子命令前缀丢失
**问题**:输入 `datacenter ` + `p` + Tab 后,`datacenter ` 前缀被 `param` 覆盖,整行只剩 `param`
**根因**`linenoiseEdit` 中 Tab 键处理用 `strncpy(buf, completions[0])` 整行覆盖。
**修复**:改为找到最后一个空格,只替换空格之后的当前词,保留前缀。
---
### #5 app_cmd 交互卡顿与 Tab 补全失效
**问题**:上一轮将 `cmd_recv` 改为 select 非阻塞 + EV_TIMER2(100ms) 后:
1. 回车后 `cmd>` 回显不及时,有明显卡顿感
2. 输入 `d` 后按 Tab不会弹出命令补全
**根因**`select()` 方案与 `linenoise()` 交互式行编辑器根本性不兼容——select 时终端处于规范模式行缓冲Tab 不是行终止符不会触发 select100ms 定时器引入最多 100ms 延迟。
**修复**:将 `app_cmd` 线程从定时器事件驱动改为简单阻塞循环 `while(1) { cmd_recv(); }`。`linenoise()` 自管理终端模式切换和 Tab 补全,线程阻塞在 stdin 上零延迟响应。
**验证**:编译通过。
---
### #4 app_cmd 线程启用后 CPU 飙升至 108%
**问题**`app_cmd` 线程中 `cmd_recv()` 启用后CPU 占用 108%,导致该入口被暂时屏蔽([app_cmd.cpp:117](src/system/RTU/src/app_cmd.cpp#L117) 被注释)。
**根因**
1. **死循环层面**`linenoiseEdit()`[my_cmd.cpp:107](src/public/libcmd/src/my_cmd.cpp#L107))中 `read()` 只检查了返回 `-1`,未处理返回 `0`EOF。当进程无真正控制终端时RTU 嵌入式环境常见),`read()` 立即返回 0 形成死循环。
2. **架构层面**`linenoise()` 是同步阻塞调用,却被放在 10ms 定时器 EVI_TIMER1 中执行,与其他定时器事件循环模型不兼容。
**修复内容**
1. `my_cmd.cpp``read()` 返回值判断改为 `<= 0`(含 EOF 处理);`enableRawMode()` 返回值在 `linenoise()` 中检查,失败直接返回 NULL
2. `app_cmd.cpp`:重构 `cmd_recv``cmd_recv_nonblock()`,用 `select()` 实现非阻塞 stdin 检查 + `isatty()` 过滤非终端环境,移至 EV_TIMER2100ms调用
3. `CLAUDE.md`:全文翻译为中文
**验证**:编译通过(零错误零警告),`./test/RTU < /dev/null` 运行 3 秒 CPU 占用 0.0%。
---
## 2026-06-10
### #1 libmms_m RCB 订阅编号硬编码
**问题**`mms_m_icd_report_init()` 中硬编码 `if(0 == rpt_no.compare("01"))`,只订阅编号为 `"01"` 的 RCB其他编号被丢弃无法按需灵活订阅多个 RCB 实例。
**需求**
1. 灵活可配置订阅的控制块编号
2. libmms_m 提供接口,由 libiec61850m 传入
3. 可传入一个或多个编号,不传默认 `"01"`
4. 无效数据打印错误并返回失败
**处理计划**[RCB订阅编号可配置化](./mid/RCB订阅编号可配置化.md)
**状态**:✅ 已完成
**涉及文件**`myMms_m.h`, `mms_m.h`, `mms_m.cpp`, `iec61850m.cpp`
---
### #2 libweb_server 模块缺陷修复
**问题**WebSocket 服务端模块存在 10 个缺陷含严重级别单客户端、多线程竞态、悬空指针、non-null-terminated UB和高危/中等级别(调试 printf、SBO 阻塞、LOG 格式化缺失等)。
**需求**
1. 兼容多个 WebSocket 客户端同时连接
2. 完善断连处理
3. 多线程安全保护
4. 修复 UB 和格式化问题
5. 增量推送优化(仅变化时发送)
**处理计划**[libweb_server模块分析](../工程/libweb_server模块分析.md)
**状态**:✅ 已完成
**涉及文件**`web_server.cpp`, `ws_method.cpp`
---
### #3 libweb_server 多连接资源共享冲突
**问题**:支持多客户端后,所有连接共享同一套全局信号资源(`g_ws_out_signals` 等),一个客户端的 add/del 操作会影响其他客户端的数据推送。
**需求**
1. 每个连接独立的信号资源per-connection session
2. 连接建立时自动开辟资源,断开时自动释放
3. `ws_task()` 按 session 独立构建 JSON 推送到对应连接
**处理计划**[libweb_server模块分析](../工程/libweb_server模块分析.md)
**状态**:✅ 已完成
**涉及文件**`ws_method.h`, `ws_method.cpp`, `web_server.cpp`
---