Skip to content

Conversation

@robertkill
Copy link
Contributor

@robertkill robertkill commented Oct 14, 2025

  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

Summary by Sourcery

Fix enrollment stop sequence to improve thread safety and prevent race conditions during camera cleanup and data processing.

Bug Fixes:

  • Disconnect QImageCapture signals before stopping capture to avoid race conditions
  • Wait for processing completion flag before releasing camera resources to ensure synchronized shutdown
  • Reorder model manager unloading after thread stop to prevent resource access after deletion

Enhancements:

  • Introduce RAII-based CheckDoneGuard to automatically set m_checkDone flag after capture processing
  • Remove QCoreApplication::processEvents() call in send loop to eliminate potential reentrancy issues
  • Add debug logs around stop sequence for clearer shutdown tracing

@sourcery-ai
Copy link

sourcery-ai bot commented Oct 14, 2025

Reviewer's Guide

This PR refactors the enrollment stop sequence to address thread-safety and race conditions by disconnecting image capture signals before stopping, using a busy-wait synchronized flag with an RAII guard for task completion, reordering resource cleanup (including ModelManager unload post-blocking stop), and removing an unnecessary QCoreApplication::processEvents call.

Sequence diagram for improved enrollment stop process

sequenceDiagram
participant DriverManger
participant ErollThread
participant Camera
participant ModelManger

DriverManger->>ErollThread: invokeMethod("Stop", BlockingQueuedConnection)
ErollThread->>Camera: disconnect signals
ErollThread->>Camera: stop()
ErollThread->>Camera: reset()
ErollThread->>ErollThread: wait for m_checkDone (busy-wait)
ErollThread->>ErollThread: cleanup fileSocket
DriverManger->>ModelManger: unLoad()
DriverManger->>DriverManger: remove actionId from m_actionMap
DriverManger->>DriverManger: update charaList
Loading

Class diagram for ErollThread stop and CheckDoneGuard changes

classDiagram
class ErollThread {
  - m_imageCapture : QImageCapture*
  - m_camera : QCamera*
  - m_stopCapture : bool
  - m_checkDone : bool
  - m_fileSocket : int
  + Stop()
  + processCapturedImage(int id, const QImage &preview)
}
class CheckDoneGuard {
  - self : ErollThread*
  + CheckDoneGuard(ErollThread *s)
  + ~CheckDoneGuard()
}
ErollThread "1" o-- "1" CheckDoneGuard : uses (RAII in processCapturedImage)

class QFutureWatcher {
  + finished
}
ErollThread "1" o-- "1" QFutureWatcher : async image processing
Loading

File-Level Changes

Change Details Files
Enhanced thread synchronization and shutdown in Stop()
  • Disconnected QImageCapture signals before stopping
  • Set m_stopCapture flag and stopped the camera before reset
  • Added busy-wait loop on m_checkDone to ensure cleanup completion
  • Inserted debug logs around the wait loop
workmodule.cpp
Introduced RAII guard for m_checkDone
  • Defined CheckDoneGuard struct to set m_checkDone in its destructor
  • Moved m_checkDone assignment into guard instead of lambda
  • Captured img by value in QtConcurrent::run to avoid dangling references
workmodule.cpp
Removed unnecessary event processing to prevent reentrancy
  • Deleted QCoreApplication::processEvents() call in sendCapture loop
workmodule.cpp
Reordered resource cleanup in enrollStop()
  • Switched to Qt::BlockingQueuedConnection for Stop invocation
  • Moved ModelManager::unLoad call to after Stop completes
  • Added debug logs before and after thread stop and unload
  • Cleaned up action map and updated character list post-stop
drivermanger.cpp

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes and they look great!

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location> `workmodule.cpp:76-78` </location>
<code_context>
     m_stopCapture = true;
     m_camera->stop();
     m_camera.reset();
+    while (!m_checkDone) {
+        qDebug() << "wait check done thread:" << QThread::currentThreadId();
+        QThread::msleep(100);
+        continue;
+    }
</code_context>

<issue_to_address>
**suggestion (performance):** Busy-wait loop may block thread responsiveness.

Consider replacing the busy-wait loop with QWaitCondition or signals to avoid blocking the thread and improve responsiveness.

Suggested implementation:

```cpp
    m_mutex.lock();
    while (!m_checkDone) {
        qDebug() << "wait check done thread:" << QThread::currentThreadId();
        m_checkDoneCondition.wait(&m_mutex, 100); // Wait for up to 100ms, then re-check
    }
    m_mutex.unlock();

```

You will need to:
1. Add `QWaitCondition m_checkDoneCondition;` and `QMutex m_mutex;` as members of your `ErollThread` class.
2. Wherever `m_checkDone` is set to `true` (likely in another thread), you must call:
   ```
   m_mutex.lock();
   m_checkDone = true;
   m_checkDoneCondition.wakeAll();
   m_mutex.unlock();
   ```
   This will wake up the waiting thread in `Stop()`.
3. Make sure to `#include <QWaitCondition>` and `#include <QMutex>` at the top of your file.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +76 to +78
while (!m_checkDone) {
qDebug() << "wait check done thread:" << QThread::currentThreadId();
QThread::msleep(100);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (performance): Busy-wait loop may block thread responsiveness.

Consider replacing the busy-wait loop with QWaitCondition or signals to avoid blocking the thread and improve responsiveness.

Suggested implementation:

    m_mutex.lock();
    while (!m_checkDone) {
        qDebug() << "wait check done thread:" << QThread::currentThreadId();
        m_checkDoneCondition.wait(&m_mutex, 100); // Wait for up to 100ms, then re-check
    }
    m_mutex.unlock();

You will need to:

  1. Add QWaitCondition m_checkDoneCondition; and QMutex m_mutex; as members of your ErollThread class.
  2. Wherever m_checkDone is set to true (likely in another thread), you must call:
    m_mutex.lock();
    m_checkDone = true;
    m_checkDoneCondition.wakeAll();
    m_mutex.unlock();
    
    This will wake up the waiting thread in Stop().
  3. Make sure to #include <QWaitCondition> and #include <QMutex> at the top of your file.

workmodule.cpp Outdated
ErollThread *self;
CheckDoneGuard(ErollThread *s) : self(s) {}
~CheckDoneGuard() { self->m_checkDone = true; }
} guard(this);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

auto cleanup = qScopeGuard([&] {
// 这里的代码会在函数退出时自动执行
qDebug() << "清理资源";
});

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
@deepin-ci-robot
Copy link

deepin pr auto review

代码审查报告

drivermanger.cpp

改进建议

  1. 代码逻辑

    • ModelManger::getSingleInstanceModel().unLoad() 调用从线程停止前移到了线程停止后,这可能会导致资源释放顺序问题。建议保持原有的资源释放顺序,即先卸载模型再停止线程。
    • 添加的调试日志 qDebug() 语句在正式发布版本中应该移除或使用条件编译,避免在生产环境中产生不必要的性能开销。
  2. 代码质量

    • 在调用 QMetaObject::invokeMethod 时,参数格式不一致(一行 vs 多行),建议统一格式。
    • 缺少对 m_spErollthread 是否为空的检查,可能导致空指针解引用。
  3. 代码性能

    • 线程停止操作使用了 Qt::BlockingQueuedConnection,这会导致调用线程阻塞,需要确保这是预期的行为。
  4. 代码安全

    • 在移除 actionId 前应该确保线程已经完全停止,避免竞争条件。

workmodule.cpp

改进建议

  1. 代码逻辑

    • Stop() 方法中,断开信号槽连接的顺序应该在设置 m_stopCapture = true 之前,这样可以避免在断开连接前有新的信号触发。
    • while (!m_checkDone) 的忙等待会占用 CPU 资源,建议使用事件驱动机制或条件变量来优化。
    • processCapturedImage 中,使用 lambda 捕获 img 可能会导致悬垂引用,因为 img 是局部变量。
  2. 代码质量

    • sendCapture 方法中移除了 QCoreApplication::processEvents(),这可能会导致事件处理延迟,需要确认这是否是预期行为。
    • QFutureWatcher 的创建和删除方式可能会导致内存泄漏,建议使用智能指针或 RAII 模式管理。
    • qScopeGuard 的使用很好,但可以更明确地表达其意图。
  3. 代码性能

    • QThread::msleep(100) 的忙等待效率低下,建议使用更高效的线程同步机制。
    • 图像处理在后台线程中进行是正确的做法,但需要注意内存使用,特别是大图像处理时。
  4. 代码安全

    • close(m_fileSocket) 没有检查返回值,可能无法正确处理关闭失败的情况。
    • sendCapture 中,对 write 的返回值处理不够健壮,应该添加错误处理逻辑。

总体建议

  1. 添加适当的错误处理和日志记录,特别是在关键操作如资源释放、网络通信等。
  2. 考虑使用更现代的 C++ 特性,如智能指针、RAII 等,来管理资源生命周期。
  3. 对于多线程交互,建议使用更高级的同步机制,如条件变量、信号量等,而不是忙等待。
  4. 添加单元测试来验证多线程场景下的行为,特别是资源释放和线程停止的顺序。
  5. 考虑使用性能分析工具来识别和优化性能瓶颈。

@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: BLumia, mhduiy, robertkill, yixinshark

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@BLumia
Copy link
Member

BLumia commented Oct 15, 2025

/merge

@deepin-bot deepin-bot bot merged commit b9c4804 into linuxdeepin:master Oct 15, 2025
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants