From 5607633083cf3fa5c831603975d4e975e2c3c83f Mon Sep 17 00:00:00 2001 From: Robertkill Date: Tue, 14 Oct 2025 17:25:40 +0800 Subject: [PATCH] fix: improve enrollment stop sequence and thread safety MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Fixed thread synchronization issue by ensuring camera cleanup completes before proceeding 2. Added proper signal disconnections to prevent race conditions during stop 3. Implemented RAII pattern with CheckDoneGuard to ensure m_checkDone flag is always set 4. Reordered resource cleanup sequence for safer shutdown 5. Removed unnecessary QCoreApplication::processEvents() call that could cause reentrancy issues Log: Fixed enrollment process stop sequence to prevent application crashes Influence: 1. Test enrollment start and stop multiple times in quick succession 2. Verify camera resources are properly released after enrollment completion 3. Check that no race conditions occur during enrollment cancellation 4. Validate that face detection and anti-spoofing processes terminate cleanly 5. Test enrollment with different camera devices and configurations fix: 改进注册停止序列和线程安全性 1. 修复线程同步问题,确保相机清理完成后再继续执行 2. 添加正确的信号断开连接,防止停止过程中的竞争条件 3. 使用 CheckDoneGuard 实现 RAII 模式,确保 m_checkDone 标志始终被设置 4. 重新安排资源清理顺序以实现更安全的关闭 5. 移除可能导致重入问题的不必要 QCoreApplication::processEvents() 调用 Log: 修复注册过程停止序列,防止应用程序崩溃 Influence: 1. 测试快速连续多次启动和停止注册过程 2. 验证注册完成后相机资源是否正确释放 3. 检查注册取消过程中是否出现竞争条件 4. 验证人脸检测和活体检测过程是否干净终止 5. 使用不同的相机设备和配置测试注册功能 PMS: BUG-309915 --- drivermanger.cpp | 9 ++++----- workmodule.cpp | 19 ++++++++++++++----- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/drivermanger.cpp b/drivermanger.cpp index 720d168..98b7ca7 100644 --- a/drivermanger.cpp +++ b/drivermanger.cpp @@ -116,13 +116,12 @@ void DriverManger::enrollStop(QString actionId, ErrMsgInfo &errMsgInfo) free(actionInfo.faceChara); } } - - ModelManger::getSingleInstanceModel().unLoad(); - - QMetaObject::invokeMethod(m_spErollthread.data(), - "Stop", + qDebug() << "start Erollthread stop"; + QMetaObject::invokeMethod(m_spErollthread.data(), "Stop", Qt::BlockingQueuedConnection); m_actionMap.remove(actionId); + ModelManger::getSingleInstanceModel().unLoad(); + qDebug() << "ModelManger::unLoad"; auto charaList = m_spCharaDataManger->getCharaList(); setCharaList(charaList); diff --git a/workmodule.cpp b/workmodule.cpp index 417b49b..f2005ea 100644 --- a/workmodule.cpp +++ b/workmodule.cpp @@ -66,9 +66,19 @@ void ErollThread::run() void ErollThread::Stop() { qDebug() << "ErollThread::Stop thread:" << QThread::currentThreadId(); + disconnect(m_imageCapture.data(), &QImageCapture::readyForCaptureChanged, this, &ErollThread::readyForCapture); + disconnect(m_imageCapture.data(), &QImageCapture::imageCaptured, this, &ErollThread::processCapturedImage); + disconnect(m_imageCapture.data(), QOverload::of(&QImageCapture::errorOccurred), + this, &ErollThread::captureError); m_stopCapture = true; m_camera->stop(); m_camera.reset(); + while (!m_checkDone) { + qDebug() << "wait check done thread:" << QThread::currentThreadId(); + QThread::msleep(100); + continue; + } + qDebug() << "check done"; close(m_fileSocket); } @@ -104,7 +114,6 @@ void ErollThread::sendCapture(QImage &img) while (countSize > 0 && !m_stopCapture) { long sendSize = write(m_fileSocket, &buf[size - countSize], static_cast(countSize)); if (sendSize < 0) { - QCoreApplication::processEvents(); continue; } countSize -= static_cast(sendSize); @@ -162,11 +171,12 @@ void ErollThread::processCapturedImage(int id, const QImage &preview) QFutureWatcher *watcher = new QFutureWatcher(this); connect(watcher, &QFutureWatcher::finished, [this, watcher] { - m_checkDone = true; watcher->deleteLater(); }); - QFuture future = QtConcurrent::run([=]() { - qDebug() << "thread id:" << QThread::currentThreadId(); + QFuture future = QtConcurrent::run([this, img]() { + auto guard = qScopeGuard([this]() { + this->m_checkDone = true; + }); QImage img1 = img.convertToFormat(QImage::Format_RGB888).rgbSwapped(); SeetaImageData image; image.height = img1.height(); @@ -233,7 +243,6 @@ void ErollThread::processCapturedImage(int id, const QImage &preview) if (status == seeta::FaceAntiSpoofing::SPOOF) { QMetaObject::invokeMethod(this, "processStatus", Qt::QueuedConnection, Q_ARG(QString, m_actionId), Q_ARG(qint32, FaceEnrollNotRealHuman)); return; - } else { qDebug() << "antispoofing ok"; }