修复:跨线程数据竞争 + 协议字段越界 + 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:
@@ -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秒
|
||||
|
||||
Reference in New Issue
Block a user