Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 3 additions & 8 deletions src/editorapplication.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2019 - 2022 UnionTech Software Technology Co., Ltd.
// SPDX-FileCopyrightText: 2019-2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

Expand Down Expand Up @@ -45,13 +45,8 @@ EditorApplication::EditorApplication(int &argc, char *argv[]) : DApplication(arg
EditorApplication::~EditorApplication()
{
qDebug() << "Enter EditorApplication destructor";
// app结束时,释放
if (nullptr != StartManager::instance()) {
qDebug() << "Deleting StartManager instance";
delete StartManager::instance();
} else {
qDebug() << "StartManager instance is already null";
}
// StartManager 生命周期由 main() 接管(创建于 create(),事件循环结束后显式释放),
// 析构不得触碰,否则 D-Bus 转发进程会在退出期意外实例化单例(BUG-378901)
qDebug() << "Exit EditorApplication destructor";
qInfo() << "Application resources released";
}
Expand Down
9 changes: 7 additions & 2 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ int main(int argc, char *argv[])
qDebug() << "DTKWIDGET_CLASS_DSizeMode not defined, skipping size mode handler";
#endif

StartManager *startManager = StartManager::instance();
// 单例唯一创建点;D-Bus 转发进程走不到这里,不会实例化 StartManager
StartManager *startManager = StartManager::create();

//埋点记录启动数据
QJsonObject objStartEvent{
Expand Down Expand Up @@ -169,7 +170,11 @@ int main(int argc, char *argv[])

PerformanceMonitor::initializeAppFinish();
qDebug() << "Entering main event loop";
return app.exec();
int ret = app.exec();
// 事件循环已停止,在此显式释放单例;~EditorApplication 不再管理其生命周期
qDebug() << "Deleting StartManager instance on exit";
delete StartManager::instance();
return ret;
}
// Just send dbus message to exist editor process.
else {
Expand Down
7 changes: 6 additions & 1 deletion src/startmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ static const QString s_bookMarkKey = "advance.editor.bookmark";

StartManager *StartManager::m_instance = nullptr;

StartManager *StartManager::instance()
StartManager *StartManager::create()
{
if (m_instance == nullptr) {
qDebug() << "StartManager instance is null, creating new instance";
Expand All @@ -42,6 +42,11 @@ StartManager *StartManager::instance()
return m_instance;
}

StartManager *StartManager::instance()
{
return m_instance;
}

StartManager::~StartManager()
{
qDebug() << "Enter StartManager destructor";
Expand Down
2 changes: 2 additions & 0 deletions src/startmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ class StartManager : public QObject
int tabIndex;
};

// 唯一创建点:仅 main() 调用;其余场合一律用 instance() 纯查询
static StartManager *create();
static StartManager *instance();
explicit StartManager(QObject *parent = nullptr);
~StartManager();
Expand Down
22 changes: 13 additions & 9 deletions tests/app_ut/test_editorapplication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@
// 分支清单 → 用例映射(editorapplication.cpp):
// ctor(9) → SetUpTestSuite 真实构造 + Ctor_应用属性就位(Qt>=6 分支)
// dtor(45) → TearDownTestSuite delete s_app:
// D2/D0 双记录 + "StartManager::instance() 非空 → delete"分支
// (else 空分支不可二次构造 QApplication,函数覆盖已达成)
// D2/D0 双记录(StartManager 生命周期已移交 main(),dtor 不再触碰)
// handleQuitAction(59)
// B1 activeWindow 非空 → close
// → HandleQuitAction_ActiveWindow_ClosesIt(closeEvent 计数 + 隐藏断言)
Expand Down Expand Up @@ -444,14 +443,19 @@ TEST_F(EditorApplicationTest, PressSpace_Button_ReleasesAfter80msAndClicks)

// ---------------- dtor 前置 ----------------

// dtor(45) 前置:保证 TearDownTestSuite delete s_app 时 StartManager::instance()
// 非空,命中“Deleting StartManager instance”分支(D2/D0 双记录在 delete 时落点)
TEST_F(EditorApplicationTest, Dtor_Precondition_StartManagerInstanceAlive)
// dtor(45) 前置:~EditorApplication 已不管理 StartManager 生命周期(BUG-378901 修复:
// 创建点唯一化为 main() 中的 create(),事件循环结束后于 main() 显式释放)。
// 此处验证 instance() 为纯查询访问器,无创建副作用——TearDownTestSuite delete s_app
// 时不会意外实例化/销毁单例(D2/D0 双记录在 delete 时落点)
TEST_F(EditorApplicationTest, Dtor_Precondition_InstanceIsNonCreating)
{
// Arrange / Act:惰性单例真实构造(DBus/Iflytek 已 stub,XDG 已重定向)
// Arrange
StartManager::m_instance = nullptr;

// Act:纯查询访问器(旧实现此处会惰性创建完整单例)
StartManager *instance = StartManager::instance();

// Assert
EXPECT_NE(instance, nullptr);
EXPECT_EQ(StartManager::m_instance, instance);
// Assert:不创建,析构路径对 StartManager 零接触
EXPECT_EQ(instance, nullptr);
EXPECT_EQ(StartManager::m_instance, nullptr);
}
20 changes: 16 additions & 4 deletions tests/startmanager/test_startmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -548,25 +548,37 @@ QCoreApplication *StartManagerTest::s_app = nullptr;
// 构造 / 单例 / 析构
// ============================================================

TEST_F(StartManagerTest, Instance_FirstCall_CreatesAndReusesSingleton)
TEST_F(StartManagerTest, Create_FirstCall_CreatesAndReusesSingleton)
{
// Arrange
StartManager::m_instance = nullptr;

// Act
StartManager *p1 = StartManager::instance();
StartManager *p2 = StartManager::instance();
// Act:create() 为唯一创建点,重复调用幂等;instance() 纯查询同实例
StartManager *p1 = StartManager::create();
StartManager *p2 = StartManager::create();
StartManager *q = StartManager::instance();

// Assert:首建非空且复用同一实例
ASSERT_NE(p1, nullptr);
EXPECT_EQ(p1, p2);
EXPECT_EQ(q, p1);

// Cleanup:析构置空静态指针(覆盖 ~StartManager B2 正侧)
delete p1->m_pTimer;
delete p1;
EXPECT_EQ(StartManager::m_instance, nullptr);
}

TEST_F(StartManagerTest, Instance_NonCreating_ReturnsNullWhenAbsent)
{
// Arrange:BUG-378901 修复后 instance() 不再惰性创建
StartManager::m_instance = nullptr;

// Act / Assert:单例缺席时纯查询返回空,不得实例化
EXPECT_EQ(StartManager::instance(), nullptr);
EXPECT_EQ(StartManager::m_instance, nullptr);
}

TEST_F(StartManagerTest, Destructor_ForeignInstance_KeepsStaticPointer)
{
// Arrange:静态指针指向其他实例
Expand Down
5 changes: 5 additions & 0 deletions tests/widgets_ut/test_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ class WindowTest : public ::testing::Test {
QDir().mkpath(xdgData + "/deepin/deepin-editor/blank-files");
QDir().mkpath(xdgData + "/deepin/deepin-editor/backup-files");
QDir().mkpath(xdgData + "/deepin/deepin-editor/autoBackup-files");

// BUG-378901 修复后 instance() 为纯查询不创建,window.cpp 各调用点
// (checkTabbarForReload/removeWrapper 的 delayMallocTrim 等)依赖单例已存在;
// 套件级显式建真实例,与旧懒创建语义等价(生产路径由 main() 中 create() 保证)
StartManager::create();
}

static void TearDownTestSuite()
Expand Down
Loading