Skip to content

Commit 2233bfa

Browse files
committed
fix: resolve potential crash and resource management issues in network
module 1. Add proper destructor for DccNetwork to disconnect signals before object destruction 2. Fix potential null pointer dereference in root() method by adding null check for m_manager 3. Clean up VPN state update timer in NetManagerThreadPrivate destructor to prevent dangling timer callbacks 4. Increase thread wait timeout from 200ms to 1000ms in destructor to avoid forced thread termination during active operations 5. Replace QTimer::singleShot with a member timer for VPN state updates to prevent callback accumulation and ensure proper cleanup 6. Add mutex protection for NetworkController singleton instance and free operations to fix thread-safety issues Log: Fixed potential crashes and resource leaks in network management; improved thread safety for singleton access Influence: 1. Test network plugin initialization and destruction cycles repeatedly 2. Verify DccNetwork object creation and destruction does not cause signal-slot errors 3. Test VPN connection state changes and verify no duplicate timer callbacks 4. Test rapid VPN state transitions to confirm proper timer reset behavior 5. Test NetworkController::instance() and free() from multiple threads 6. Verify thread termination during active network operations completes gracefully 7. Check for any memory leaks or dangling pointers after repeated initialization fix: 修复网络模块中的潜在崩溃和资源管理问题 1. 为 DccNetwork 添加正确的析构函数,在对象销毁前断开信号连接 2. 修复 root() 方法中潜在的空指针解引用问题,添加对 m_manager 的空值检查 3. 清理 NetManagerThreadPrivate 析构函数中的 VPN 状态更新定时器,防止悬 空定时器回调 4. 将析构函数中的线程等待超时从 200ms 增加到 1000ms,避免正在执行的任务 被强制终止 5. 用成员定时器替换 QTimer::singleShot 进行 VPN 状态更新,防止回调累积并 确保正确清理 6. 为 NetworkController 单例的 instance() 和 free() 操作添加互斥锁保护, 解决线程安全问题 Log: 修复了网络管理中的潜在崩溃和资源泄漏问题,改善了单例访问的线程安 全性 Influence: 1. 反复测试网络插件的初始化和销毁周期 2. 验证 DccNetwork 对象的创建和销毁不会导致信号槽错误 3. 测试 VPN 连接状态变化,确认没有重复的定时器回调 4. 测试快速切换 VPN 状态,验证定时器重置行为正确 5. 从多个线程测试 NetworkController::instance() 和 free() 6. 验证线程在活跃网络操作期间能优雅地终止 7. 检查重复初始化后是否有内存泄漏或悬空指针 PMS: BUG-353781
1 parent 7c86100 commit 2233bfa

5 files changed

Lines changed: 38 additions & 10 deletions

File tree

dcc-network/operation/dccnetwork.cpp

Lines changed: 9 additions & 2 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 "dccnetwork.h"
@@ -33,9 +33,16 @@ DccNetwork::DccNetwork(QObject *parent)
3333
QMetaObject::invokeMethod(this, "init", Qt::QueuedConnection);
3434
}
3535

36+
DccNetwork::~DccNetwork()
37+
{
38+
if (m_manager) {
39+
disconnect(m_manager, &NetManager::request, this, &DccNetwork::request);
40+
}
41+
}
42+
3643
NetItem *DccNetwork::root() const
3744
{
38-
return m_manager->root();
45+
return m_manager ? m_manager->root() : nullptr;
3946
}
4047

4148
bool DccNetwork::CheckPasswordValid(const QString &key, const QString &password)

dcc-network/operation/dccnetwork.h

Lines changed: 2 additions & 1 deletion
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
#ifndef DCCNETWORK_H
@@ -23,6 +23,7 @@ class DccNetwork : public QObject
2323

2424
public:
2525
explicit DccNetwork(QObject *parent = nullptr);
26+
~DccNetwork() override;
2627
NetItem *root() const;
2728
Q_INVOKABLE static bool CheckPasswordValid(const QString &key, const QString &password);
2829

net-view/operation/private/netmanagerthreadprivate.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ NetManagerThreadPrivate::NetManagerThreadPrivate()
9898
, m_netCheckAvailable(false)
9999
, m_isSleeping(false)
100100
, m_showPageTimer(nullptr)
101+
, m_vpnStateUpdateTimer(nullptr)
101102
, m_supportWireless(false)
102103
{
103104
moveToThread(m_thread);
@@ -106,12 +107,15 @@ NetManagerThreadPrivate::NetManagerThreadPrivate()
106107

107108
NetManagerThreadPrivate::~NetManagerThreadPrivate()
108109
{
110+
// 先断开所有信号,防止析构期间再有新任务(如singleShot)入队
111+
disconnect();
109112
m_thread->quit();
110-
m_thread->wait(QDeadlineTimer(200));
113+
// 增大等待时间至1000ms,避免50ms定时器回调等正在执行的任务被terminate强杀
114+
m_thread->wait(QDeadlineTimer(1000));
111115
if (m_thread->isRunning()) {
112116
m_thread->terminate();
113117
}
114-
m_thread->wait(QDeadlineTimer(200));
118+
m_thread->wait(QDeadlineTimer(500));
115119
delete m_thread;
116120
}
117121

@@ -416,6 +420,9 @@ void NetManagerThreadPrivate::doInit()
416420
}
417421
Q_EMIT itemAdded("Root", vpnControlItem);
418422

423+
m_vpnStateUpdateTimer = new QTimer(this);
424+
m_vpnStateUpdateTimer->setSingleShot(true);
425+
m_vpnStateUpdateTimer->setInterval(55);
419426
auto updateVPNConnectionState = [this]() {
420427
auto itemList = NetworkController::instance()->vpnController()->items();
421428
NetType::NetDeviceStatus state = NetType::DS_Disconnected;
@@ -431,8 +438,10 @@ void NetManagerThreadPrivate::doInit()
431438
}
432439
Q_EMIT dataChanged(DataChanged::VPNConnectionStateChanged, "NetVPNControlItem", QVariant::fromValue(state));
433440
};
434-
auto vpnConnectionStateChanged = [this, updateVPNConnectionState] {
435-
QTimer::singleShot(50, this, updateVPNConnectionState);
441+
connect(m_vpnStateUpdateTimer, &QTimer::timeout, this, updateVPNConnectionState);
442+
auto vpnConnectionStateChanged = [this] {
443+
// 使用成员定时器,重复触发时自动重置计时,防止多次触发累积
444+
m_vpnStateUpdateTimer->start();
436445
};
437446

438447
auto vpnItemChanged = [this, vpnConnectionStateChanged] {
@@ -596,6 +605,11 @@ void NetManagerThreadPrivate::clearData()
596605
delete m_autoScanTimer;
597606
m_autoScanTimer = nullptr;
598607
}
608+
if (m_vpnStateUpdateTimer) {
609+
m_vpnStateUpdateTimer->stop();
610+
delete m_vpnStateUpdateTimer;
611+
m_vpnStateUpdateTimer = nullptr;
612+
}
599613
if (m_secretAgent) {
600614
delete m_secretAgent;
601615
m_secretAgent = nullptr;

net-view/operation/private/netmanagerthreadprivate.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ protected Q_SLOTS:
299299
QMap<NetworkDetails *, QString> m_detailsItemsMap; // 存储 NetworkDetails 指针到唯一ID的映射
300300
QString m_showPageCmd;
301301
QTimer *m_showPageTimer;
302+
QTimer *m_vpnStateUpdateTimer;
302303
QString m_newVPNuuid;
303304
bool m_supportWireless;
304305
};

src/networkcontroller.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: 2018 - 2022 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

@@ -18,6 +18,8 @@
1818
#include "wirelessdevice.h"
1919
#include "connectivityhandler.h"
2020

21+
#include <QGlobalStatic>
22+
2123
// const static QString networkService = "org.deepin.dde.Network1";
2224
// const static QString networkPath = "/org/deepin/dde/Network1";
2325
static QString localeName;
@@ -102,10 +104,12 @@ void NetworkController::onDeviceAdded(QList<NetworkDeviceBase *> device)
102104

103105
NetworkController::~NetworkController() = default;
104106

107+
// 文件级互斥锁,instance() 和 free() 共用,防止数据竞争
108+
Q_GLOBAL_STATIC(QMutex, s_networkControllerMutex)
109+
105110
NetworkController *NetworkController::instance()
106111
{
107-
static QMutex m;
108-
QMutexLocker locker(&m);
112+
QMutexLocker locker(s_networkControllerMutex());
109113
if (!m_networkController) {
110114
m_networkController = new NetworkController;
111115
};
@@ -114,6 +118,7 @@ NetworkController *NetworkController::instance()
114118

115119
void NetworkController::free()
116120
{
121+
QMutexLocker locker(s_networkControllerMutex());
117122
if (m_networkController) {
118123
m_networkController->deleteLater();
119124
m_networkController = nullptr;

0 commit comments

Comments
 (0)