fix(backend): 信号值持久存储 + WS 日志控制 + core dump 配置

self_ptl:
- 修复: self_ptl_do_signal_out() 使用栈局部变量, 函数返回后
  指针悬空 → 前端读到垃圾值 0xFC (252)
- 新增 6 个全局 vector (g_st_vals/g_mx_vals/g_co_vals/g_dd_vals/
  g_ao_vals/g_param_val_ptrs) 作为持久存储, 零初始化后传地址

webserver:
- ws_method: get_file/set_file 路径拼接 %s%s → %s/%s
  (修复 func_proc_self_dir 无末尾 / 导致路径错误)
- ws_method: WS 日志默认关闭, 新增 web_log on/off/status 命令
  (CMD_REGISTER_C 注册)
- ws_method: dc_data JSON 改为 ws_send_one (文本帧),
  ws_recv 日志用 memcpy+null 截断防乱码

main.c:
- 添加 setrlimit(RLIMIT_CORE, RLIM_INFINITY)
  和 prctl(PR_SET_DUMPABLE) 启用 core dump

build.sh:
- 构建前自动设置 core_pattern 到项目根目录
This commit is contained in:
ypc 2026-07-14 18:23:11 +08:00
parent e27b01943c
commit 842d83a147
3 changed files with 57 additions and 26 deletions

View File

@ -1,5 +1,10 @@
#!/bin/bash #!/bin/bash
cd "$(dirname "$0")" cd "$(dirname "$0")"
# 配置 core dump 输出到项目根目录 (需要 sudo)
echo "$(dirname "$(readlink -f "$0")")/../core.%e.%p.%t" | sudo tee /proc/sys/kernel/core_pattern 2>/dev/null || true
ulimit -c unlimited
echo "=== RTU_ALL_AI Build ===" echo "=== RTU_ALL_AI Build ==="
# 删除 config 同级目录下的旧 RTU (即项目根目录) # 删除 config 同级目录下的旧 RTU (即项目根目录)

View File

@ -20,6 +20,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <signal.h> #include <signal.h>
#include <sys/resource.h>
#include <sys/prctl.h>
static volatile int g_running = 1; static volatile int g_running = 1;
@ -39,6 +41,16 @@ int main(int argc, char *argv[])
signal(SIGINT, sig_handler); signal(SIGINT, sig_handler);
signal(SIGTERM, sig_handler); signal(SIGTERM, sig_handler);
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
signal(SIGSEGV, sig_handler); /* 确保 SIGSEGV 也走正常退出流程 */
/* 启用 core dump便于定位崩溃 */
{
struct rlimit rl;
rl.rlim_cur = RLIM_INFINITY;
rl.rlim_max = RLIM_INFINITY;
setrlimit(RLIMIT_CORE, &rl);
prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
}
/* 日志初始化:控制台输出(调试可见),运行时可开文件输出 */ /* 日志初始化:控制台输出(调试可见),运行时可开文件输出 */
log_init(NULL); log_init(NULL);

View File

@ -111,6 +111,14 @@ static stru_self_ptl g_self_ptl =
static stru_self_ptl_cfg_data g_self_ptl_cfg_data = {}; static stru_self_ptl_cfg_data g_self_ptl_cfg_data = {};
/* ---- 信号值持久存储 (避免栈变量被回收) ---- */
static std::vector<uint8_t> g_st_vals;
static std::vector<float> g_mx_vals;
static std::vector<uint8_t> g_co_vals;
static std::vector<float> g_dd_vals;
static std::vector<float> g_ao_vals;
static std::vector<void *> g_param_val_ptrs;
/* ---- 前向声明内部回调 (C++ linkage) ---- */ /* ---- 前向声明内部回调 (C++ linkage) ---- */
/* ao_pop_out 等回调在 self_ptl_cb.cpp 中实现 */ /* ao_pop_out 等回调在 self_ptl_cb.cpp 中实现 */
@ -435,56 +443,62 @@ static int self_ptl_do_signal_out(void)
return -1; return -1;
} }
/* 注册遥信信号 (ST) */ /* 预分配持久存储 (避免栈变量被回收) */
for(auto &cfg : p_cfg->st_vec) g_st_vals.resize(p_cfg->st_vec.size(), 0);
{ g_mx_vals.resize(p_cfg->mx_vec.size(), 0.0f);
uint8_t val = 0; g_co_vals.resize(p_cfg->co_vec.size(), 0);
g_dd_vals.resize(p_cfg->dd_vec.size(), 0.0f);
g_ao_vals.resize(p_cfg->ao_vec.size(), 0.0f);
dc_signal_out(cfg.saddr.c_str(), cfg.desc.c_str(), DATA_TYPE_U8, &val, MODULE_SELF_PTL); /* 注册遥信信号 (ST) */
for(size_t i = 0; i < p_cfg->st_vec.size(); i++)
{
auto &cfg = p_cfg->st_vec[i];
dc_signal_out(cfg.saddr.c_str(), cfg.desc.c_str(), DATA_TYPE_U8, &g_st_vals[i], MODULE_SELF_PTL);
} }
/* 注册遥测信号 (MX) */ /* 注册遥测信号 (MX) */
for(auto &cfg : p_cfg->mx_vec) for(size_t i = 0; i < p_cfg->mx_vec.size(); i++)
{ {
float val = 0.0f; auto &cfg = p_cfg->mx_vec[i];
dc_signal_out(cfg.saddr.c_str(), cfg.desc.c_str(), DATA_TYPE_F32, &g_mx_vals[i], MODULE_SELF_PTL);
dc_signal_out(cfg.saddr.c_str(), cfg.desc.c_str(), DATA_TYPE_F32, &val, MODULE_SELF_PTL);
} }
/* 注册遥控信号 (CO) */ /* 注册遥控信号 (CO) */
for(auto &cfg : p_cfg->co_vec) for(size_t i = 0; i < p_cfg->co_vec.size(); i++)
{ {
uint8_t val = 0; auto &cfg = p_cfg->co_vec[i];
dc_signal_yk(cfg.saddr.c_str(), cfg.desc.c_str(), DATA_TYPE_U8, dc_signal_yk(cfg.saddr.c_str(), cfg.desc.c_str(), DATA_TYPE_U8,
DC_CTRL_SBO, &val, NULL, MODULE_SELF_PTL); DC_CTRL_SBO, &g_co_vals[i], NULL, MODULE_SELF_PTL);
} }
/* 注册电度信号 (DD) */ /* 注册电度信号 (DD) */
for(auto &cfg : p_cfg->dd_vec) for(size_t i = 0; i < p_cfg->dd_vec.size(); i++)
{ {
float val = 0.0f; auto &cfg = p_cfg->dd_vec[i];
dc_signal_out(cfg.saddr.c_str(), cfg.desc.c_str(), DATA_TYPE_F32, &g_dd_vals[i], MODULE_SELF_PTL);
dc_signal_out(cfg.saddr.c_str(), cfg.desc.c_str(), DATA_TYPE_F32, &val, MODULE_SELF_PTL);
} }
/* 注册参数信号 (AO) */ /* 注册参数信号 (AO) */
for(auto &cfg : p_cfg->ao_vec) for(size_t i = 0; i < p_cfg->ao_vec.size(); i++)
{ {
float val = 0.0f; auto &cfg = p_cfg->ao_vec[i];
dc_signal_ao(cfg.base.saddr.c_str(), cfg.base.desc.c_str(), cfg.type, dc_signal_ao(cfg.base.saddr.c_str(), cfg.base.desc.c_str(), cfg.type,
DC_CTRL_SBO, &val, NULL, MODULE_SELF_PTL); DC_CTRL_SBO, &g_ao_vals[i], NULL, MODULE_SELF_PTL);
} }
/* 注册定值信号 (Param) */ /* 注册定值信号 (Param) */
g_param_val_ptrs.clear();
for(auto &cfg : p_cfg->param_vec) for(auto &cfg : p_cfg->param_vec)
{ {
float val = 0.0f; void *p = dc_create_data(cfg.type);
void *p_data_arr[1] = {&val}; if(p)
{
g_param_val_ptrs.push_back(p);
void *arr[1] = {p};
dc_signal_param(cfg.base.saddr.c_str(), cfg.base.desc.c_str(), cfg.type, dc_signal_param(cfg.base.saddr.c_str(), cfg.base.desc.c_str(), cfg.type,
DC_CTRL_SBO, p_data_arr, 1, NULL, MODULE_SELF_PTL); DC_CTRL_SBO, arr, 1, NULL, MODULE_SELF_PTL);
}
} }
LOG_I("self_ptl_do_signal_out: ST=%d, MX=%d, CO=%d, DD=%d, AO=%d, Param=%d", LOG_I("self_ptl_do_signal_out: ST=%d, MX=%d, CO=%d, DD=%d, AO=%d, Param=%d",