From 9445d0b75a0f33b6ff9b8a9a8270630ff1eedb71 Mon Sep 17 00:00:00 2001 From: fuleyi Date: Thu, 14 May 2026 14:18:20 +0800 Subject: [PATCH] fix: resolve face enrollment freeze issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Set m_stopCapture flag to true before invoking Stop method to signal capture loop exit 2. Convert m_stopCapture from bool to std::atomic for thread-safe cross- thread access 3. Add retry logic for socket write operations to handle EAGAIN/ EWOULDBLOCK errors 4. Implement maximum 100 retries with 1ms delay to prevent infinite loop in sendCapture Influence: 1. Test face enrollment stop operation to verify no freeze occurs 2. Test concurrent stop request during active image capture 3. Verify socket write handles temporary unavailability gracefully 4. Test retry mechanism reaches maximum limit and breaks loop correctly 5. Verify normal face enrollment completion still works correctly 6. Test multiple rapid start/stop enrollment cycles fix: 解决录入人脸时卡死的问题 1. 在调用 Stop 方法前设置 m_stopCapture 标志为 true 以通知捕获循环退出 2. 将 m_stopCapture 从 bool 转换为 std::atomic 实现跨线程安全访问 3. 为 socket 写操作添加重试逻辑以处理 EAGAIN/EWOULDBLOCK 错误 4. 实现最大 100 次重试和 1ms 延迟以防止 sendCapture 中出现死循环 Influence: 1. 测试人脸录入停止操作验证不再发生卡死 2. 测试活动图像捕获期间的并发停止请求 3. 验证 socket 写操作能优雅处理临时不可用情况 4. 测试重试机制达到最大限制时正确跳出循环 5. 验证正常人脸录入完成流程仍然正常工作 6. 测试多次快速开始/停止录入循环 PMS: BUG-352653 Change-Id: Ice3f9e91fc29f36aa4315da9d4b6b049d6b190fe --- drivermanger.cpp | 3 ++- workmodule.cpp | 13 ++++++++++++- workmodule.h | 7 +++++-- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/drivermanger.cpp b/drivermanger.cpp index 98b7ca7..58332f8 100644 --- a/drivermanger.cpp +++ b/drivermanger.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2022 - 2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -117,6 +117,7 @@ void DriverManger::enrollStop(QString actionId, ErrMsgInfo &errMsgInfo) } } qDebug() << "start Erollthread stop"; + m_spErollthread->m_stopCapture = true; QMetaObject::invokeMethod(m_spErollthread.data(), "Stop", Qt::BlockingQueuedConnection); m_actionMap.remove(actionId); diff --git a/workmodule.cpp b/workmodule.cpp index c538578..60a28ef 100644 --- a/workmodule.cpp +++ b/workmodule.cpp @@ -111,11 +111,22 @@ void ErollThread::sendCapture(QImage &img) } unsigned long countSize = size; + int retryCount = 0; while (countSize > 0 && !m_stopCapture) { long sendSize = write(m_fileSocket, &buf[size - countSize], static_cast(countSize)); if (sendSize < 0) { - continue; + if (errno == EAGAIN || errno == EWOULDBLOCK) { + retryCount++; + if (retryCount > 100) { + break; + } + QThread::msleep(1); + continue; + } + qWarning() << "write error:" << strerror(errno); + break; } + retryCount = 0; countSize -= static_cast(sendSize); } free(buf); diff --git a/workmodule.h b/workmodule.h index 3dc5873..5d7ff35 100644 --- a/workmodule.h +++ b/workmodule.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2022 - 2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -6,6 +6,7 @@ #define WORKMODULE_H #include +#include #include #include #include @@ -46,6 +47,9 @@ private Q_SLOTS: void captureError(int err, QImageCapture::Error, const QString &errorString); void processCapturedImage(int id, const QImage &preview); +public: + std::atomic m_stopCapture; + private: QScopedPointer m_camera; QScopedPointer m_imageCapture; @@ -53,7 +57,6 @@ private Q_SLOTS: QString m_actionId; int m_fileSocket; bool m_bFirst; - bool m_stopCapture; bool m_checkDone; };