Skip to content

Commit 3165c9b

Browse files
committed
fix: defer DSysInfo queries in plugins to avoid dlopen deadlock
The control center loads plugins via QPluginLoader during startup. Several plugins called DSysInfo::uosType()/uosEditionType()/deepinType()/isDeepin() in global/static initialization (namespace-scope const variables), which runs while the dynamic loader holds the glibc/ld.so loader lock. On systems where /etc/os-version is missing or malformed, DSysInfo internally emits qWarning(), which enters the dtklog appender pipeline. Meanwhile another thread already holding the dtklog write lock formats %{function} via QRegularExpression/pcre2, which can trigger TLS/loader initialization and wait on the same loader lock. This forms a classic deadlock: Thread A: loader lock -> DSysInfo -> qWarning -> wait dtklog lock Thread B: dtklog lock -> %{function} regex/pcre2/TLS -> wait loader lock Replace the namespace-scope const globals (UosType, IsServerSystem, IsCommunitySystem, etc.) with static inline lazy-init helper functions that compute the value once on first runtime call via function-local statics. This keeps the "compute once" semantics but moves the DSysInfo calls out of the dlopen global constructor phase, breaking the loader-lock side of the deadlock chain. Affected plugins: sound, power, commoninfo, deepinid. The helpers use `static inline` to preserve internal linkage (matching the original const globals) and avoid ODR/symbol collisions across plugins that share the same utils.h include guard name. Log: defer DSysInfo queries in plugins to avoid dlopen deadlock fix: 延迟插件中 DSysInfo 的调用以避免 dlopen 死锁 控制中心启动时通过 QPluginLoader 加载插件。多个插件在全局/静态初始化 (命名空间作用域 const 变量)中调用了 DSysInfo::uosType() 等接口,这些 代码在动态加载器持有 glibc/ld.so 加载锁期间执行。 当 /etc/os-version 缺失或格式异常时,DSysInfo 内部会触发 qWarning(), 进入 dtklog appender 写入流程。此时另一个线程已持有 dtklog 写锁,正在 格式化 %{function},经由 QRegularExpression/pcre2 触发 TLS/加载器初始化, 并等待同一把加载锁,形成经典死锁: 线程 A:加载锁 -> DSysInfo -> qWarning -> 等待 dtklog 锁 线程 B:dtklog 锁 -> %{function} regex/pcre2/TLS -> 等待加载锁 将命名空间作用域的 const 全局变量(UosType、IsServerSystem 等)替换为 static inline 懒加载辅助函数,通过函数局部 static 在首次运行时调用时 计算一次。保留"只计算一次"语义,但把 DSysInfo 调用移出 dlopen 全局构造 阶段,打断死锁链中加载锁一侧。 涉及插件:sound、power、commoninfo、deepinid。 辅助函数使用 static inline 保持内部链接(与原 const 全局变量一致), 避免多个共用 utils.h include guard 名的插件之间产生 ODR/符号冲突。 Log: 延迟插件中 DSysInfo 的调用以避免 dlopen 死锁 Change-Id: I1b72cc0a72252730e640997b5481c96f3989343e
1 parent 1bcefde commit 3165c9b

8 files changed

Lines changed: 98 additions & 40 deletions

File tree

src/plugin-commoninfo/operation/utils.h

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
1+
//SPDX-FileCopyrightText: 2018 - 2026 UnionTech Software Technology Co., Ltd.
22
//
33
//SPDX-License-Identifier: GPL-3.0-or-later
44
#ifndef UTILS_H
@@ -31,15 +31,47 @@ inline constexpr qint32 ActionIconSize=30;//大图标角标大小
3131
inline constexpr qint32 ActionListSize=26;//list图标角标大小
3232

3333

34-
const DSysInfo::UosType UosType = DSysInfo::uosType();
35-
const DSysInfo::UosEdition UosEdition = DSysInfo::uosEditionType();
36-
const bool IsServerSystem = (DSysInfo::UosServer == UosType);//是否是服务器版
37-
const bool IsCommunitySystem = (DSysInfo::UosCommunity == UosEdition);//是否是社区版
38-
const bool IsProfessionalSystem = (DSysInfo::UosProfessional == UosEdition);//是否是专业版
39-
const bool IsHomeSystem = (DSysInfo::UosHome == UosEdition);//是否是个人版
40-
const bool IsEducationSystem = (DSysInfo::UosEducation == UosEdition); // 是否是教育版
41-
const bool IsDeepinDesktop = (DSysInfo::DeepinDesktop == DSysInfo::deepinType());//是否是Deepin桌面
42-
const bool IsNotDeepinUos = !DSysInfo::isDeepin(); // 是否是 Deepin/Uos 以外的发行版
34+
static inline bool isServerSystem()
35+
{
36+
static const bool serverSystem = DSysInfo::UosServer == DSysInfo::uosType();
37+
return serverSystem;
38+
}
39+
40+
static inline bool isCommunitySystem()
41+
{
42+
static const bool communitySystem = DSysInfo::UosCommunity == DSysInfo::uosEditionType();
43+
return communitySystem;
44+
}
45+
46+
static inline bool isProfessionalSystem()
47+
{
48+
static const bool professionalSystem = DSysInfo::UosProfessional == DSysInfo::uosEditionType();
49+
return professionalSystem;
50+
}
51+
52+
static inline bool isHomeSystem()
53+
{
54+
static const bool homeSystem = DSysInfo::UosHome == DSysInfo::uosEditionType();
55+
return homeSystem;
56+
}
57+
58+
static inline bool isEducationSystem()
59+
{
60+
static const bool educationSystem = DSysInfo::UosEducation == DSysInfo::uosEditionType();
61+
return educationSystem;
62+
}
63+
64+
static inline bool isDeepinDesktop()
65+
{
66+
static const bool deepinDesktop = DSysInfo::DeepinDesktop == DSysInfo::deepinType();
67+
return deepinDesktop;
68+
}
69+
70+
static inline bool isNotDeepinUos()
71+
{
72+
static const bool notDeepinUos = !DSysInfo::isDeepin();
73+
return notDeepinUos;
74+
}
4375

4476

4577
template <typename T>

src/plugin-deepinid/operation/deepinidinterface.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd.
1+
// SPDX-FileCopyrightText: 2025 - 2026 UnionTech Software Technology Co., Ltd.
22
//
33
// SPDX-License-Identifier: GPL-3.0-or-later
44

@@ -16,7 +16,7 @@ DeepinIDInterface::DeepinIDInterface(QObject *parent)
1616

1717
QString DeepinIDInterface::editionName() const
1818
{
19-
if (IsCommunitySystem) {
19+
if (isCommunitySystem()) {
2020
return tr("deepin");
2121
} else {
2222
return tr("UOS");

src/plugin-deepinid/operation/deepinidworker.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd.
1+
// SPDX-FileCopyrightText: 2025 - 2026 UnionTech Software Technology Co., Ltd.
22
//
33
// SPDX-License-Identifier: GPL-3.0-or-later
44

@@ -407,7 +407,7 @@ QString DeepinWorker::loadCodeURL()
407407
};
408408

409409
QString oauthURI = "https://login.uniontech.com";
410-
if (IsCommunitySystem) {
410+
if (isCommunitySystem()) {
411411
oauthURI = "https://login.deepin.org";
412412
}
413413

@@ -422,7 +422,7 @@ QString DeepinWorker::loadCodeURL()
422422

423423
void DeepinWorker::getLicenseState()
424424
{
425-
if (IsCommunitySystem) {
425+
if (isCommunitySystem()) {
426426
m_model->setActivation(true);
427427
return;
428428
}

src/plugin-deepinid/operation/utils.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd.
1+
// SPDX-FileCopyrightText: 2025 - 2026 UnionTech Software Technology Co., Ltd.
22
//
33
// SPDX-License-Identifier: GPL-3.0-or-later
44

@@ -27,9 +27,9 @@ QString getUrlTitle()
2727
{
2828
QString url;
2929
if (qEnvironmentVariableIsEmpty("DEEPIN_PRE")) {
30-
url = IsCommunitySystem ? QStringLiteral("https://login.deepin.org") : QStringLiteral("https://login.uniontech.com");
30+
url = isCommunitySystem() ? QStringLiteral("https://login.deepin.org") : QStringLiteral("https://login.uniontech.com");
3131
} else {
32-
url = IsCommunitySystem ? QStringLiteral("https://login-pre.deepin.org") : QStringLiteral("https://login-pre.uniontech.com");
32+
url = isCommunitySystem() ? QStringLiteral("https://login-pre.deepin.org") : QStringLiteral("https://login-pre.uniontech.com");
3333
}
3434
return url;
3535
}
@@ -196,12 +196,12 @@ QStringList getDeviceInfo()
196196

197197
QString getEditionName()
198198
{
199-
return IsCommunitySystem ? "deepin" : "UOS";
199+
return isCommunitySystem() ? "deepin" : "UOS";
200200
}
201201

202202
QString getIconName()
203203
{
204-
return IsCommunitySystem ? "deepin-id" : "uos-id";
204+
return isCommunitySystem() ? "deepin-id" : "uos-id";
205205
}
206206

207207
}; // namespace utils

src/plugin-deepinid/operation/utils.h

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd.
1+
// SPDX-FileCopyrightText: 2025 - 2026 UnionTech Software Technology Co., Ltd.
22
//
33
// SPDX-License-Identifier: GPL-3.0-or-later
44

@@ -31,13 +31,35 @@ DCORE_USE_NAMESPACE
3131
#define DEEPINCLIENT_PATH QStringLiteral("/com/deepin/deepinid/Client")
3232
#define DEEPINCLIENT_INTERFACE QStringLiteral("com.deepin.deepinid.Client")
3333

34-
const DSysInfo::UosType UosType = DSysInfo::uosType();
35-
const DSysInfo::UosEdition UosEdition = DSysInfo::uosEditionType();
36-
const bool IsServerSystem = (DSysInfo::UosServer == UosType); // 是否是服务器版
37-
const bool IsCommunitySystem = (DSysInfo::UosCommunity == UosEdition); // 是否是社区版
38-
const bool IsProfessionalSystem = (DSysInfo::UosProfessional == UosEdition); // 是否是专业版
39-
const bool IsHomeSystem = (DSysInfo::UosHome == UosEdition); // 是否是个人版
40-
const bool IsDeepinDesktop = (DSysInfo::DeepinDesktop == DSysInfo::deepinType()); // 是否是Deepin桌面
34+
static inline bool isServerSystem()
35+
{
36+
static const bool serverSystem = DSysInfo::UosServer == DSysInfo::uosType();
37+
return serverSystem;
38+
}
39+
40+
static inline bool isCommunitySystem()
41+
{
42+
static const bool communitySystem = DSysInfo::UosCommunity == DSysInfo::uosEditionType();
43+
return communitySystem;
44+
}
45+
46+
static inline bool isProfessionalSystem()
47+
{
48+
static const bool professionalSystem = DSysInfo::UosProfessional == DSysInfo::uosEditionType();
49+
return professionalSystem;
50+
}
51+
52+
static inline bool isHomeSystem()
53+
{
54+
static const bool homeSystem = DSysInfo::UosHome == DSysInfo::uosEditionType();
55+
return homeSystem;
56+
}
57+
58+
static inline bool isDeepinDesktop()
59+
{
60+
static const bool deepinDesktop = DSysInfo::DeepinDesktop == DSysInfo::deepinType();
61+
return deepinDesktop;
62+
}
4163

4264
enum SyncType {
4365
Sound,

src/plugin-power/operation/powermodel.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
1+
//SPDX-FileCopyrightText: 2018 - 2026 UnionTech Software Technology Co., Ltd.
22
//
33
//SPDX-License-Identifier: GPL-3.0-or-later
44
#include "powermodel.h"
@@ -331,7 +331,7 @@ void PowerModel::setBalancePerformanceSupported(bool isBalancePerformanceSupport
331331

332332
void PowerModel::setSuspend(bool suspend)
333333
{
334-
bool enable = !IsServerSystem && suspend;
334+
bool enable = !isServerSystem() && suspend;
335335
if (m_isSuspend != enable) {
336336
m_isSuspend = enable;
337337

@@ -341,7 +341,7 @@ void PowerModel::setSuspend(bool suspend)
341341

342342
void PowerModel::setHibernate(bool hibernate)
343343
{
344-
bool enable = !IsServerSystem && hibernate;
344+
bool enable = !isServerSystem() && hibernate;
345345
if (m_isHibernate != enable) {
346346
m_isHibernate = enable;
347347

src/plugin-power/operation/utils.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
1+
//SPDX-FileCopyrightText: 2018 - 2026 UnionTech Software Technology Co., Ltd.
22
//
33
//SPDX-License-Identifier: GPL-3.0-or-later
44
#ifndef UTILS_H
@@ -35,9 +35,11 @@ T valueByQSettings(const QStringList& configFiles,
3535
return failback.value<T>();
3636
}
3737

38-
inline const static Dtk::Core::DSysInfo::UosType UosType = Dtk::Core::DSysInfo::uosType();
39-
inline const static bool IsServerSystem =
40-
(Dtk::Core::DSysInfo::UosServer == UosType); // 是否是服务器版
38+
static inline bool isServerSystem()
39+
{
40+
static const bool serverSystem = Dtk::Core::DSysInfo::UosServer == Dtk::Core::DSysInfo::uosType();
41+
return serverSystem;
42+
}
4143

4244
inline static bool isVirtualEnvironment()
4345
{

src/plugin-sound/operation/soundmodel.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: 2024 - 2027 UnionTech Software Technology Co., Ltd.
1+
// SPDX-FileCopyrightText: 2024 - 2026 UnionTech Software Technology Co., Ltd.
22
//
33
// SPDX-License-Identifier: GPL-3.0-or-later
44
#include "soundmodel.h"
@@ -13,8 +13,11 @@
1313

1414
Q_LOGGING_CATEGORY(DdcSoundModel, "dcc-sound-model")
1515

16-
const static Dtk::Core::DSysInfo::UosType UosType = Dtk::Core::DSysInfo::uosType();
17-
const static bool IsServerSystem = (Dtk::Core::DSysInfo::UosServer == UosType); //是否是服务器版
16+
static bool isServerSystem()
17+
{
18+
static const bool serverSystem = Dtk::Core::DSysInfo::UosServer == Dtk::Core::DSysInfo::uosType();
19+
return serverSystem;
20+
}
1821

1922
static const QMap<DDesktopServices::SystemSoundEffect, QString> SOUND_EFFECT_MAP{
2023
{ DDesktopServices::SystemSoundEffect::SSE_Notifications, "message" },
@@ -97,7 +100,7 @@ SoundModel::SoundModel(QObject *parent)
97100
{ tr("Error"), DDesktopServices::SSE_Error },
98101
};
99102

100-
if (IsServerSystem) {
103+
if (isServerSystem()) {
101104
m_soundEffectMapBattery.removeOne({ tr("Wake up"), DDesktopServices::SSE_WakeUp });
102105
m_soundEffectMapPower.removeOne({ tr("Wake up"), DDesktopServices::SSE_WakeUp });
103106
}
@@ -733,4 +736,3 @@ void SoundModel::setShowInputBluetoothMode(bool newShowInputBluetoothMode)
733736
m_showInputBluetoothMode = newShowInputBluetoothMode;
734737
emit showInputBluetoothModeChanged();
735738
}
736-

0 commit comments

Comments
 (0)