From be55bd0f49e050b7c2df071f4e2b53184799edd0 Mon Sep 17 00:00:00 2001 From: zhanghongyuan Date: Tue, 29 Sep 2026 21:52:58 +0800 Subject: [PATCH] fix: stop backend write thread before teardown in ~Settings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DSettings::setBackend() moves the backend to a dedicated write thread and only DSettings::destroyed quits and waits for it. ~Settings() deleted the backend first while never destroying DSettings, so the main thread could free the backend (and its QSettings) while the write thread was still running doSetOption, causing a use-after-free SIGSEGV (exit 139) in CI test_settings, reliably reproduced by the BUG102351 case in full-suite runs. Destroy DSettings before deleting m_backend so the write thread is stopped first; this also fixes the DSettings instance leak. Log: 修复 Settings 析构与 backend 写线程竞态导致的段错误(CI UT 退出码 139) Influence: Settings 析构顺序调整,无接口变化;顺带修复 DSettings 实例泄漏 --- src/common/settings.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/common/settings.cpp b/src/common/settings.cpp index a2ab6274..2cfcfed5 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -239,6 +239,16 @@ Settings::~Settings() if (s_pSetting == this) { s_pSetting = nullptr; } + // 先销毁 DSettings 再销毁后端:setBackend() 会将 backend moveToThread + // 到专门的写线程,doSetOption/doSync 经队列在该线程异步落盘,仅 + // DSettings::destroyed 会 quit+wait 该线程。若先 delete m_backend, + // 主线程销毁 backend(及其 QSettings)会与写线程在途的 doSetOption + // 竞态(QSettings UAF → SIGSEGV,CI test_settings 套件复现),且 + // settings 裸指针从不释放;此处先停写线程,后端销毁即无并发风险 + if (settings != nullptr) { + delete settings; + settings = nullptr; + } if (m_backend != nullptr) { qDebug() << "Cleaning up settings backend"; delete m_backend;