update 修改读取参数,修复并发日志崩溃

dev_lsy
liusiyang 1 month ago
parent cbb7737c9a
commit 65948e2eee

@ -103,7 +103,8 @@ public:
}
if (cpu_floatData != NULL)
{
delete cpu_floatData;
// 与 LoadEngine 中的 new float[datalength] 配对,必须用 delete[]
delete[] cpu_floatData;
cpu_floatData = NULL;
}
}

@ -337,7 +337,8 @@ int AIModel_Impl::LoadEngine(int ngpuIdx)
{
if (steamNodeconfig->cpu_floatData)
{
delete steamNodeconfig->cpu_floatData;
// 与下面 new float[datalength] 配对,必须用 delete[]
delete[] steamNodeconfig->cpu_floatData;
steamNodeconfig->cpu_floatData = NULL;
}

@ -14,6 +14,7 @@
#include <string.h>
#include <sys/time.h>
#include <vector>
#include <mutex>
#include "ImgCheckConfig.h"
#include "CheckErrorCodeDefine.hpp"
using namespace std;
@ -61,6 +62,9 @@ struct DetLog
std::vector<std::string> logList;
bool bPrintStr; // 是否打印日志
int addLogLevel;
// 保护 logList:同一个 DetLog(如图片结果的日志)会被实例主线程(Run/CheckRun)
// 与任务线程(AI 推理/分类) 并发写入,无锁 push_back 会造成 vector 堆破坏。
std::mutex mtx_log;
DetLog()
{
@ -68,11 +72,19 @@ struct DetLog
}
void Init()
{
std::lock_guard<std::mutex> lock(mtx_log);
logList.clear();
bPrintStr = false;
addLogLevel = DET_LOG_LEVEL_3;
}
// 线程安全地获取日志快照
std::vector<std::string> GetLogs()
{
std::lock_guard<std::mutex> lock(mtx_log);
return logList;
}
template <typename... Args>
void AddCheckstr(PrintLevel_ step, std::string stepStr, const std::string &format, Args... args)
{
@ -105,6 +117,7 @@ struct DetLog
printf("%s\n", str.c_str());
}
std::lock_guard<std::mutex> lock(mtx_log);
logList.push_back(str);
}
template <typename... Args>
@ -141,16 +154,20 @@ struct DetLog
if (LogLevel <= addLogLevel)
{
std::lock_guard<std::mutex> lock(mtx_log);
logList.push_back(str);
}
}
void printLog(std::string str)
{
printf("===========================%s==============================\n", str.c_str());
{
std::lock_guard<std::mutex> lock(mtx_log);
for (auto strl : logList)
{
printf("%s\n", strl.c_str());
}
}
printf("==========================================================\n");
}
};

@ -203,6 +203,8 @@ private:
std::condition_variable m_task_cv_;
std::shared_ptr<std::thread> ptr_thread_Draw;
std::condition_variable m_drawComplate_cv_;
// 正在执行中的绘制任务数(受 m_task_mutex_ 保护),用于 WaiteDrawComplate 精确等待
int m_nDrawProcessingNum = 0;
};
#endif

@ -790,7 +790,6 @@ int CameraCheckAnalysisy::CheckImgRun()
if (m_pCheck_Result->getImgPushComplate())
{
curcheckStep = Check_Step_Complete; // 进入到预图片检测阶段
m_pCheck_Result->SetCheckStep(curcheckStep);
}
else
{
@ -807,7 +806,12 @@ int CameraCheckAnalysisy::CheckImgRun()
m_pdetlog->AddCheckstr(PrintLevel_0, "CheckImgRun", "========came %s Check ALL end time %ld ms %s",
m_pCheck_Result->cameraBaseResult->strCameraName.c_str(), tend - m_pCheck_Result->time_start, strTimg.c_str());
InsertCameraLog();
// 结果与日志(det_LogList)全部写完后,才置为 Check_Step_Complete,
// 通知 Det_Product 结果可以交付调用方;并且整个收尾过程保持在
// mtx_WaiteImg 锁内,与 StartCheck() 对 m_pCheck_Result 的赋值互斥,
// 避免同一 shared_ptr 被并发 reset/赋值(会造成控制块双重释放)。
std::lock_guard<std::mutex> lock(mtx_WaiteImg);
m_pCheck_Result->SetCheckStep(Check_Step_Complete);
m_bHaveImgeDet = false;
m_pCheck_Result.reset();
@ -851,8 +855,12 @@ int CameraCheckAnalysisy::InsertCameraLog()
}
// 1、把图片的相关日志 写到 返回 日志中。
// 注意:DetLog 可能仍被实例线程写入,使用 GetLogs() 做加锁快照,避免并发遍历。
{
std::vector<std::string> imgLogs = pImageResult->detlog->GetLogs();
m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(),
pImageResult->detlog->logList.begin(), pImageResult->detlog->logList.end());
imgLogs.begin(), imgLogs.end());
}
std::string str = "";
char buffer[256];
// 2、把缺陷信息 写的 返回日志中。
@ -883,8 +891,9 @@ int CameraCheckAnalysisy::InsertCameraLog()
if (QX_info->result == QX_RESULT_TYPE_NG)
{
std::shared_ptr<DetLog> pQxLog = pDetResult->pQx_ErrorList->at(qxidx).detlog;
std::vector<std::string> qxLogs = pQxLog->GetLogs();
m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(),
pQxLog->logList.begin(), pQxLog->logList.end());
qxLogs.begin(), qxLogs.end());
}
}
@ -900,8 +909,9 @@ int CameraCheckAnalysisy::InsertCameraLog()
if (QX_info->result == QX_RESULT_TYPE_YS)
{
std::shared_ptr<DetLog> pQxLog = pDetResult->pQx_ErrorList->at(qxidx).detlog;
std::vector<std::string> qxLogs = pQxLog->GetLogs();
m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(),
pQxLog->logList.begin(), pQxLog->logList.end());
qxLogs.begin(), qxLogs.end());
}
}
@ -917,8 +927,9 @@ int CameraCheckAnalysisy::InsertCameraLog()
if (QX_info->result == QX_RESULT_TYPE_OK)
{
std::shared_ptr<DetLog> pQxLog = pDetResult->pQx_ErrorList->at(qxidx).detlog;
std::vector<std::string> qxLogs = pQxLog->GetLogs();
m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(),
pQxLog->logList.begin(), pQxLog->logList.end());
qxLogs.begin(), qxLogs.end());
}
}
@ -934,8 +945,9 @@ int CameraCheckAnalysisy::InsertCameraLog()
if (QX_info->result == QX_RESULT_TYPE_NoJduge)
{
std::shared_ptr<DetLog> pQxLog = pDetResult->pQx_ErrorList->at(qxidx).detlog;
std::vector<std::string> qxLogs = pQxLog->GetLogs();
m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(),
pQxLog->logList.begin(), pQxLog->logList.end());
qxLogs.begin(), qxLogs.end());
}
}
}
@ -947,8 +959,11 @@ int CameraCheckAnalysisy::InsertCameraLog()
}
// 3、把相机的日志 写到 返回日志中。
{
std::vector<std::string> camLogs = m_pCheck_Result->detlog->GetLogs();
m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(),
m_pCheck_Result->detlog->logList.begin(), m_pCheck_Result->detlog->logList.end());
camLogs.begin(), camLogs.end());
}
{
sprintf(buffer, " =====================Product Log =============================");
@ -956,8 +971,11 @@ int CameraCheckAnalysisy::InsertCameraLog()
m_CheckResult_shareP->det_LogList.push_back(str);
}
// 4、把产品相关日志 写到 返回日志中。
{
std::vector<std::string> productLogs = m_pCheck_Result->productBaseResult->detlog->GetLogs();
m_CheckResult_shareP->det_LogList.insert(m_CheckResult_shareP->det_LogList.end(),
m_pCheck_Result->productBaseResult->detlog->logList.begin(), m_pCheck_Result->productBaseResult->detlog->logList.end());
productLogs.begin(), productLogs.end());
}
}
return 0;
}

@ -67,8 +67,10 @@ std::string CheckUtil::getCurrentDate()
// 将 tv_sec 转换为 time_t 类型,代表自1970年1月1日起的秒数
time_t raw_time = tv.tv_sec;
// 使用 localtime 将 time_t 转换为 tm 结构体
struct tm *time_info = localtime(&raw_time);
// 使用 localtime_r 转换为 tm 结构体。
// 注意:localtime() 返回共享的静态缓冲区,多线程并发调用会互相覆盖(tm 内容串数据)。
struct tm time_buf;
struct tm *time_info = localtime_r(&raw_time, &time_buf);
// 使用字符串流格式化为 "YYYY-MM-DD"
std::ostringstream oss;
@ -84,7 +86,9 @@ std::string CheckUtil::getCurTimeHMS()
gettimeofday(&tv, NULL); // 获取当前时间
time_t raw_time = tv.tv_sec;
struct tm *time_info = localtime(&raw_time);
// 使用 localtime_r(线程安全);localtime() 的静态缓冲会被其它线程并发覆盖
struct tm time_buf;
struct tm *time_info = localtime_r(&raw_time, &time_buf);
int millisec = tv.tv_usec / 1000; // 微秒转毫秒

@ -1109,11 +1109,27 @@ void ImageResultJudge::ThreadDraw()
while (!m_bExit)
{
std::this_thread::sleep_for(std::chrono::milliseconds(0));
// 等待是否有任务
std::shared_ptr<ImageResultJudge::DrawInfo> draw = GetTask();
std::shared_ptr<ImageResultJudge::DrawInfo> draw;
// 取任务与 计数+1 必须在同一把锁内完成,
// 否则 WaiteDrawComplate 可能在任务已出队但尚未计数的间隙提前返回。
{
std::unique_lock<std::mutex> lock(m_task_mutex_);
m_task_cv_.wait(lock, [this]()
{ return !m_DrawInfoList.empty(); });
draw = std::move(m_DrawInfoList.front());
m_DrawInfoList.pop();
m_nDrawProcessingNum++;
}
// 把任务发送给对应的任务处理函数进行处理
DrawResultTask(draw);
{
std::lock_guard<std::mutex> lock(m_task_mutex_);
m_nDrawProcessingNum--;
}
m_drawComplate_cv_.notify_all();
}
}
@ -1214,10 +1230,13 @@ int ImageResultJudge::DrawResultTask(std::shared_ptr<ImageResultJudge::DrawInfo>
int ImageResultJudge::WaiteDrawComplate()
{
// 等待 所有绘制任务真正执行完成。
// 旧实现只等待队列为空,而任务在取出时即已出队,绘制仍在后台线程进行,
// 调用方(结果存图/拷贝)可能与绘制线程并发读写同一张图片。
{
std::unique_lock<std::mutex> lock(m_task_mutex_);
m_drawComplate_cv_.wait(lock, [this]()
{ return m_DrawInfoList.empty(); });
{ return m_DrawInfoList.empty() && m_nDrawProcessingNum == 0; });
}
return 0;
}

@ -161,7 +161,7 @@ int ConfigManager::UpdateConfig()
ReadFlawCodeConfig(defect_list_file);
bool bFileName = false;
// std::regex pattern(R"(param_[0-9]\.json)");
std::regex pattern(R"(param_(\d+|left|right)\.json)");
std::regex pattern(R"(param_.*\.json)");
if (!fs::exists(m_strConfigRootPath))
{
std::cerr << "目录不存在: " << m_strConfigRootPath << std::endl;

@ -185,12 +185,12 @@ std::string Extract_ALL::Extract_Product_Name(std::string strPath, int userflag)
// std::cout << strPath << std::endl;
fs::path p = fs::path(strPath);
fs::path lastDir = p.parent_path().filename();
fs::path lastDir = p.parent_path().parent_path().filename();
std::string name = lastDir.string();
if (name.length()<7)
if (name.empty())
{
lastDir = p.parent_path().parent_path().filename();
lastDir = p.parent_path().filename();
name = lastDir.string();
}
@ -212,24 +212,26 @@ std::string Extract_ALL::Extract_Channel_Name(std::string strPath, int userflag)
}
int Extract_ALL::Read_Image_List(std::string strPath, std::string strproduct)
{
std::string strSearchImgPath = strPath + "/*.bmp";
std::vector<std::string> vecExt = {".bmp", ".png", ".jpg", ".jpeg", ".tif", ".tiff"};
for (size_t i = 0; i < vecExt.size(); i++)
{
std::string strSearchImgPath = strPath + "/*" + vecExt[i];
Read_Camera_Product_Image(strSearchImgPath, 0, strproduct);
// strSearchImgPath = strPath + "/*.png";
// Read_Camera_Product_Image(strSearchImgPath, 1);
}
return 0;
}
int Extract_ALL::Read_Image_List(std::string strPath_left, std::string strPath_right, std::string strproduct)
{
std::string strSearchImgPath = strPath_left + "/*.bmp";
std::vector<std::string> vecExt = {".bmp", ".png", ".jpg", ".jpeg", ".tif", ".tiff"};
for (size_t i = 0; i < vecExt.size(); i++)
{
std::string strSearchImgPath = strPath_left + "/*" + vecExt[i];
Read_Camera_Product_Image(strSearchImgPath, 0, strproduct);
strSearchImgPath = strPath_right + "/*.bmp";
strSearchImgPath = strPath_right + "/*" + vecExt[i];
Read_Camera_Product_Image(strSearchImgPath, 0, strproduct);
// strSearchImgPath = strPath + "/*.png";
// Read_Camera_Product_Image(strSearchImgPath, 1);
}
return 0;
}

Loading…
Cancel
Save