fix: 优雅退出 — 3 模块补 EV_STOP + 每日工作总结记录
web_server/iec104/plc 的 task_event_recv 事件掩码缺失 EV_STOP, 导致 ^C 后这 3 个线程永远卡在死循环不退. 修复: 掩码添加 | EV_STOP; plc 补 EV_STOP handler. 新增 docs/superpowers/DAILY_LOG_2026-07-14.md 总结今天 所有调试问题与修复经验, 后续优先查阅.
This commit is contained in:
parent
55476a0028
commit
a6f9384e66
|
|
@ -0,0 +1,104 @@
|
|||
# 2026-07-14 调试记录
|
||||
|
||||
## 一、前端数据持久化 BUG
|
||||
|
||||
**现象**:重启后端,前端仍显示旧信号。
|
||||
|
||||
**原因**:`signal-store.js` 用 `localStorage` 持久化,WS 重连后恢复旧数据。
|
||||
|
||||
**修复**:删除 localStorage,纯内存。WS 断连时 `SignalStore.clear()`。
|
||||
|
||||
---
|
||||
|
||||
## 二、in 信号移除(全栈)
|
||||
|
||||
`dc_signal_out_link_with_callback` 已覆盖 in 的核心功能(获取指针+回调),in 的独立 saddr 命名空间无实际价值。
|
||||
|
||||
**涉及**:datacenter API(6 文件) + libplc + webserver + 前端(8 文件) + 测试。总计 18 文件。
|
||||
|
||||
---
|
||||
|
||||
## 三、self_ptl 栈变量导致信号值 252
|
||||
|
||||
**现象**:OUT 页所有信号值显示 252 (0xFC)。
|
||||
|
||||
**原因**:`self_ptl_do_signal_out()` 用栈局部变量 `uint8_t val=0` 注册信号,函数返回后栈被回收,`dc_signal_out` 存的指针悬空。
|
||||
|
||||
**修复**:新增 6 个全局 `static vector` 作为持久存储,`resize` 零初始化后传 `&vec[i]`。
|
||||
|
||||
---
|
||||
|
||||
## 四、前端表格重构
|
||||
|
||||
**问题**:信号页面列不标准,缺少序号。
|
||||
|
||||
**修复**:统一表格格式 `# | saddr | desc | type | val | [extra] | 操作`。用 `data-action` 事件委托替代 inline onclick(避免转义引号问题)。
|
||||
|
||||
---
|
||||
|
||||
## 五、增量刷新(取代全局刷新)
|
||||
|
||||
**问题**:`Router.dispatch()` 发现 hash 没变直接 return,后端推送到达不刷新。用 `Router.reload()` 又导致全局重绘,正在编辑的输入框被清掉。
|
||||
|
||||
**修复**:
|
||||
- `SignalStore.update()` 增加增量 DOM 刷新——仅更新 `tr[data-saddr]` 行的 `.cell-val` 等单元格
|
||||
- 新增 `Router.reload()` 备用(切换页面时仍需要整页渲染)
|
||||
|
||||
---
|
||||
|
||||
## 六、删除信号后不立即消失
|
||||
|
||||
**原因**:`SignalActions.del` 调 `Router.dispatch`,hash 不变被跳过。
|
||||
|
||||
**修复**:`SignalStore.remove()` 直接 `removeChild` 删除 DOM 行(带 fade 动画),不等后端确认。`batchDel` 每项也调用 `SignalStore.remove`。
|
||||
|
||||
---
|
||||
|
||||
## 七、数据中心 desc 含空格错位
|
||||
|
||||
**原因**:`datacenter.js` 用 `line.split(/\s+/)` 按空白解析文本列,desc 含空格被拆散。
|
||||
|
||||
**修复**:后端 `dc_data` JSON 改为 `ws_send_one`(文本帧),前端接收 `data.type === 'dc_data'` 直接用结构化字段,不再解析文本。
|
||||
|
||||
---
|
||||
|
||||
## 八、内联输入框
|
||||
|
||||
OUT/YK/AO 的"设置"按钮改为 `<input>` + 按钮,Enter 触发发送。Param 同样改造。
|
||||
|
||||
---
|
||||
|
||||
## 九、后端修复
|
||||
|
||||
| 问题 | 修复 |
|
||||
|------|------|
|
||||
| `get_file`/`set_file` 路径拼接少 `/` | `"%s%s"` → `"%s/%s"` |
|
||||
| WS 日志打印乱码 | `memcpy` 到零初始化 buffer 再 `%s` |
|
||||
| WS 日志刷屏 | 新增 `web_log on/off/status` 命令,默认关闭 |
|
||||
| core dump 未启用 | `main.c` 加 `setrlimit` + `prctl`;`build.sh` 设 `core_pattern` |
|
||||
| 3 个模块 EV_STOP 缺失 | web_server/iec104/plc 事件掩码补 `\| EV_STOP`;plc 补 handler |
|
||||
|
||||
---
|
||||
|
||||
## 十、经验教训
|
||||
|
||||
1. **`func_proc_self_dir` 返回不带末尾 `/`**,拼接路径必须手动加 `/`。
|
||||
2. **栈变量地址传给持久模块 = 必崩**,信号值必须用 static/global/heap。
|
||||
3. **SPA 路由器 `hash === currentHash` 跳过渲染**适用于导航,不适用于数据驱动刷新,需独立 `reload()`。
|
||||
4. **前端增量更新优于全局重绘**,尤其在频繁推送(100ms)场景下。
|
||||
5. **`task_event_recv` 的 mask 必须包含 `EV_STOP`**,否则线程无法退出。
|
||||
|
||||
---
|
||||
|
||||
## 十一、文件变更索引
|
||||
|
||||
| 分类 | 文件 | 关键变更 |
|
||||
|------|------|----------|
|
||||
| datacenter | myDatacenter.h, dc_internal.h, dc_core.cpp, dc_signal_query.cpp, dc_signal_show.cpp, (dc_signal_in.cpp 删除) | in 信号移除 |
|
||||
| libplc | plc.cpp | in→out_link + EV_STOP |
|
||||
| self_ptl | self_ptl.cpp | 栈→global vector |
|
||||
| webserver | ws_method.cpp, web_server.cpp, web_server.h | 路径/日志/web_log/EV_STOP |
|
||||
| frontend | signal-store.js, ui.js, router.js, index.html | 增量刷新/内联输入/删除/事件委托 |
|
||||
| frontend | datacenter.js, signals.js, param.js, plc_debug.js, plc_config.js | 表格重构/inline input/PLC 重写 |
|
||||
| main.c | main.c | core dump 配置 |
|
||||
| build.sh | build.sh | core_pattern |
|
||||
|
|
@ -1311,7 +1311,7 @@ void *app_iec(void *arg)
|
|||
while (1)
|
||||
{
|
||||
task_event_recv(p_app->p_event,
|
||||
EV_TIMER1 | EV_TIMER2 | EV_TIMER3 | EV_IEC_RX_COM,
|
||||
EV_TIMER1 | EV_TIMER2 | EV_TIMER3 | EV_IEC_RX_COM | EV_STOP,
|
||||
TASK_EVENT_FLAG_OR | TASK_EVENT_FLAG_CLEAR,
|
||||
TASK_EVENT_WAIT_FOREVER,
|
||||
&event);
|
||||
|
|
|
|||
|
|
@ -1817,11 +1817,16 @@ void *app_plc(void *arg)
|
|||
while (1)
|
||||
{
|
||||
task_event_recv(p_app->p_event,
|
||||
EV_TIMER1 | EV_TIMER2 | EV_TIMER3,
|
||||
EV_TIMER1 | EV_TIMER2 | EV_TIMER3 | EV_STOP,
|
||||
TASK_EVENT_FLAG_OR | TASK_EVENT_FLAG_CLEAR,
|
||||
TASK_EVENT_WAIT_FOREVER,
|
||||
&event);
|
||||
|
||||
if (event & EV_STOP)
|
||||
{
|
||||
LOG_I("app_plc: received EV_STOP, exiting");
|
||||
break;
|
||||
}
|
||||
if (event & EV_TIMER1)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -412,7 +412,7 @@ void *app_web_server(void *arg)
|
|||
while (1)
|
||||
{
|
||||
task_event_recv(p_app->p_event,
|
||||
EV_TIMER1 | EV_TIMER2 | EV_TIMER3,
|
||||
EV_TIMER1 | EV_TIMER2 | EV_TIMER3 | EV_STOP,
|
||||
TASK_EVENT_FLAG_OR | TASK_EVENT_FLAG_CLEAR,
|
||||
TASK_EVENT_WAIT_FOREVER,
|
||||
&event);
|
||||
|
|
|
|||
Loading…
Reference in New Issue