Fix mutex lock issues (OCR and FR)
This commit is contained in:
@@ -1046,6 +1046,46 @@ namespace ANSCENTER
|
||||
MoveDetectsHandler _handler;
|
||||
const size_t QUEUE_SIZE = 10;
|
||||
std::recursive_mutex _mutex;
|
||||
std::atomic<bool> _modelLoading{ false };
|
||||
|
||||
// Pre-inference gate for ANSFDBase subclasses
|
||||
bool PreInferenceCheck(const char* caller) {
|
||||
if (_modelLoading.load()) return false;
|
||||
auto lk = TryLockWithTimeout(caller);
|
||||
if (!lk.owns_lock()) return false;
|
||||
if (!_licenseValid || !_isInitialized)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
struct ModelLoadingGuard {
|
||||
std::atomic<bool>& flag;
|
||||
explicit ModelLoadingGuard(std::atomic<bool>& f) : flag(f) { flag.store(true); }
|
||||
~ModelLoadingGuard() { flag.store(false); }
|
||||
ModelLoadingGuard(const ModelLoadingGuard&) = delete;
|
||||
ModelLoadingGuard& operator=(const ModelLoadingGuard&) = delete;
|
||||
};
|
||||
|
||||
std::unique_lock<std::recursive_mutex> TryLockWithTimeout(
|
||||
const char* caller, unsigned int timeoutMs = 5000)
|
||||
{
|
||||
const auto deadline = std::chrono::steady_clock::now()
|
||||
+ std::chrono::milliseconds(timeoutMs);
|
||||
std::unique_lock<std::recursive_mutex> lk(_mutex, std::defer_lock);
|
||||
while (!lk.try_lock()) {
|
||||
if (std::chrono::steady_clock::now() >= deadline) {
|
||||
_logger.LogWarn(caller,
|
||||
"Mutex acquisition timed out after "
|
||||
+ std::to_string(timeoutMs) + " ms"
|
||||
+ (_modelLoading.load() ? " (model loading in progress)" : ""),
|
||||
__FILE__, __LINE__);
|
||||
return lk;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
return lk;
|
||||
}
|
||||
|
||||
ANSCENTER::EngineType engineType;
|
||||
|
||||
bool _facelivenessEngineValid{ false };
|
||||
|
||||
@@ -99,6 +99,7 @@ namespace ANSCENTER {
|
||||
std::vector<Object> output;
|
||||
output.clear();
|
||||
if (!_licenseValid) {
|
||||
if (_modelLoading.load()) return {};
|
||||
this->_logger.LogError("ANSOVFBFD::RunInference", "Invalid license", __FILE__, __LINE__);
|
||||
return output;
|
||||
}
|
||||
@@ -180,6 +181,7 @@ namespace ANSCENTER {
|
||||
std::vector<Object> output;
|
||||
output.clear();
|
||||
if (!_licenseValid) {
|
||||
if (_modelLoading.load()) return {};
|
||||
this->_logger.LogError("ANSOVFBFD::RunInference", "Invalid license", __FILE__, __LINE__);
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -102,6 +102,7 @@ namespace ANSCENTER {
|
||||
std::vector<Object> ANSOVFD::RunInference(const cv::Mat& input, const std::string& camera_id, bool useDynamicImage, bool validateFace, bool facelivenessCheck) {
|
||||
// ── DML device-lost recovery (outside mutex) ──────────────
|
||||
if (_dmlDeviceLost && _face_detector) {
|
||||
if (_modelLoading.load()) return {};
|
||||
// The DML session is broken — recreate on CPU
|
||||
try {
|
||||
auto cpuDetector = std::make_unique<ANSCENTER::SCRFD>(
|
||||
@@ -136,6 +137,7 @@ namespace ANSCENTER {
|
||||
std::vector<Object> ANSOVFD::RunInference(const cv::Mat& input, bool useDynamicImage, bool validateFace, bool facelivenessCheck) {
|
||||
// ── DML device-lost recovery (outside mutex) ──────────────
|
||||
if (_dmlDeviceLost && _face_detector) {
|
||||
if (_modelLoading.load()) return {};
|
||||
try {
|
||||
auto cpuDetector = std::make_unique<ANSCENTER::SCRFD>(
|
||||
_scrfdModelPath, ANSCENTER::EngineType::CPU);
|
||||
|
||||
@@ -73,6 +73,7 @@ namespace ANSCENTER {
|
||||
std::vector<Object> output;
|
||||
output.clear();
|
||||
if (!_licenseValid) {
|
||||
if (_modelLoading.load()) return {};
|
||||
this->_logger.LogError("ANSCNNFD::RunInference", "Invalid license", __FILE__, __LINE__);
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -114,6 +114,7 @@ namespace ANSCENTER {
|
||||
std::vector<Object> output;
|
||||
output.clear();
|
||||
if (!_licenseValid) {
|
||||
if (_modelLoading.load()) return {};
|
||||
this->_logger.LogError("ANSRETINAFD::RunInference", "Invalid license", __FILE__, __LINE__);
|
||||
return output;
|
||||
}
|
||||
@@ -184,6 +185,7 @@ namespace ANSCENTER {
|
||||
std::vector<Object> output;
|
||||
output.clear();
|
||||
if (!_licenseValid) {
|
||||
if (_modelLoading.load()) return {};
|
||||
this->_logger.LogError("ANSRETINAFD::RunInference", "Invalid license", __FILE__, __LINE__);
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -223,12 +223,14 @@ namespace ANSCENTER {
|
||||
bool useDynamicImage,
|
||||
bool validateFace)
|
||||
{
|
||||
if (_modelLoading.load()) return {};
|
||||
// Phase 1: Validation + image preprocessing (brief lock)
|
||||
cv::Mat im;
|
||||
bool croppedFace;
|
||||
float scoreThreshold;
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||||
auto lock = TryLockWithTimeout("ANSSCRFDFD::Inference");
|
||||
if (!lock.owns_lock()) return {};
|
||||
|
||||
if (!_licenseValid) {
|
||||
_logger.LogError("ANSSCRFDFD::Inference", "Invalid license", __FILE__, __LINE__);
|
||||
@@ -411,7 +413,9 @@ namespace ANSCENTER {
|
||||
|
||||
|
||||
std::vector<Object> ANSSCRFDFD::InferenceDynamic(const cv::Mat& input, const std::string& camera_id) {
|
||||
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||||
if (_modelLoading.load()) return {};
|
||||
auto lock = TryLockWithTimeout("ANSSCRFDFD::InferenceDynamic");
|
||||
if (!lock.owns_lock()) return {};
|
||||
std::vector<Object> output;
|
||||
|
||||
try {
|
||||
|
||||
@@ -218,6 +218,7 @@ namespace ANSCENTER {
|
||||
std::vector<Object> outputs;
|
||||
outputs.clear();
|
||||
if (!_licenseValid) {
|
||||
if (_modelLoading.load()) return {};
|
||||
this->_logger.LogError("ANSOVSCRFDFD::RunInference", "Invalid license", __FILE__, __LINE__);
|
||||
return outputs;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user