修复:跨线程数据竞争 + 协议字段越界 + UDP 发送失败吞错

- 并发安全:PowerManger 新增 m_stateMutex,保护 m_pmCurrentState /
  m_currentDisBreakerState / m_CcuColCmd / faultCode,并封装
  addFaultCode/clearFaultCodes/getFaultCodes 访问器
- SystemData 新增跨线程读访问器(getDynVoltageLink/getPowerBusStatus/
  getDcdcStatus/getDeviceCommonStatus 等)及配电故障码集合加锁访问
- upmsg buildMsg / httpserver pushSystemData / LowerCommManager 均改为
  持锁快照,避免 listen 线程与 comm 线程撕裂读写
- 修复析构顺序:先删 httpServer 再删其他对象,避免 use-after-free
- 修复 ccuState reserved2 越界读(协议预留 2 字节,结构体仅声明 1),
  修正 coutMsg 中 SOC 门限/功率限制字段打印
- udpComm::sendDisSysCmd 不再吞掉异常,返回 sendMsg 实际结果并记录 ERROR,
  新增 SendDisSysCmdFailsWithoutSocket 单测
- 新增 fullFeeder 全类型 UDP 集成仿真器与 fetch-data/clean-data 脚本,
  .gitignore 补充 SQLite 运行期文件与 fullFeeder 二进制
This commit is contained in:
zjk
2026-08-21 11:36:19 +08:00
parent 7819ea621f
commit 12f0dee86e
20 changed files with 2406 additions and 285 deletions
+29 -5
View File
@@ -86,11 +86,14 @@ PowerManger::PowerManger()
PowerManger::~PowerManger()
{
m_commThread.Stop();
delete m_lowerCommManager; // 先停止监听线程,确保其不再调用 DB
// 必须先停 HTTP 线程(stop() 内部 pthread_join 阻塞等待线程退出),
// 否则 HTTP 线程每秒仍会读取 m_systemData / m_lowerCommManager / m_upperCommManager,
// 导致 use-after-free。
delete m_httpServer;
delete m_lowerCommManager; // 停止监听线程,确保其不再调用 DB
delete m_db;
delete m_upperCommManager;
delete m_systemData;
delete m_httpServer;
delete m_systemData; // 最后删除,此时无任何线程引用
}
//---------------------------------------------------------
@@ -374,10 +377,28 @@ void PowerManger::initControlCmd()
}
void PowerManger::addFaultCode(unsigned int code)
{
std::lock_guard<std::mutex> lock(m_stateMutex);
faultCode.push_back(code);
}
void PowerManger::clearFaultCodes()
{
std::lock_guard<std::mutex> lock(m_stateMutex);
faultCode.clear();
}
std::vector<unsigned int> PowerManger::getFaultCodes() const
{
std::lock_guard<std::mutex> lock(m_stateMutex);
return faultCode;
}
unsigned char PowerManger::getFaultLevel()
{
unsigned char maxLevel = 0;
for (auto code : faultCode) {
for (auto code : getFaultCodes()) {
// 提取0xabcd中的b位 (右移8位后取低4位)
unsigned char level = (code >> 8) & 0xF;
if (level > maxLevel) {
@@ -391,7 +412,10 @@ bool PowerManger::commLoop()
{
while(!m_commThread.IsQuitRequested())
{
m_CcuColCmd.heartbeat++;
{
std::lock_guard<std::mutex> lock(m_stateMutex);
m_CcuColCmd.heartbeat++;
}
m_lowerCommManager->processPeriodicTasks();
m_upperCommManager->processPeriodicTasks();
// 延时1秒