Skip to content

fix: 修复 DSysInfo 在 AArch64 架构下的线程安全问题#540

Merged
18202781743 merged 1 commit intolinuxdeepin:masterfrom
18202781743:master
Feb 5, 2026
Merged

fix: 修复 DSysInfo 在 AArch64 架构下的线程安全问题#540
18202781743 merged 1 commit intolinuxdeepin:masterfrom
18202781743:master

Conversation

@18202781743
Copy link
Contributor

在 AArch64 弱内存模型下,DSysInfoPrivate 的多个 ensure* 函数由于缺乏
互斥锁保护,在多线程并发访问时(如应用商店后台服务)会导致以下问题:

  1. 引用计数损坏:由于读取到初始化一半的 QString 指针,导致非对齐访问触发 SIGBUS。
  2. 堆内存损坏:多个线程同时解析文件并操作 QMap/QByteArray 导致 double free。
  3. 状态可见性问题:一个核心修改了初始化标志位,但其他核心看到的成员变量尚未完成写入。

本修改通过在 DSysInfoPrivate 中引入 QMutex,确保了单例初始化过程的原子性
和内存可见性。

Log: 修复 AArch64 架构下 DSysInfo 随机触发 SIGBUS/SIGSEGV 崩溃的问题。
Bug: https://pms.uniontech.com/bug-view-350151.html
Change-Id: Ib23b078c3eef5c3ad8aef5a36035ac4839d11bb2

在 AArch64 弱内存模型下,DSysInfoPrivate 的多个 ensure* 函数由于缺乏
互斥锁保护,在多线程并发访问时(如应用商店后台服务)会导致以下问题:
1. 引用计数损坏:由于读取到初始化一半的 QString 指针,导致非对齐访问触发 SIGBUS。
2. 堆内存损坏:多个线程同时解析文件并操作 QMap/QByteArray 导致 double free。
3. 状态可见性问题:一个核心修改了初始化标志位,但其他核心看到的成员变量尚未完成写入。

本修改通过在 DSysInfoPrivate 中引入 QMutex,确保了单例初始化过程的原子性
和内存可见性。

Log: 修复 AArch64 架构下 DSysInfo 随机触发 SIGBUS/SIGSEGV 崩溃的问题。
Bug: https://pms.uniontech.com/bug-view-350151.html
Change-Id: Ib23b078c3eef5c3ad8aef5a36035ac4839d11bb2
@18202781743 18202781743 requested review from BLumia and mhduiy February 5, 2026 02:43
@deepin-ci-robot
Copy link
Contributor

deepin pr auto review

这段代码主要是在 DSysInfoPrivate 类中引入了互斥锁(QMutexQMutexLocker),以解决多线程环境下的并发访问问题。以下是对这段代码的详细审查意见,包括语法逻辑、代码质量、代码性能和代码安全四个方面:

1. 语法逻辑

  • 互斥锁的使用:代码正确地使用了 QMutexLocker,利用 RAII(Resource Acquisition Is Initialization)机制,在函数退出时自动释放锁,避免了忘记解锁的风险。这一点是符合 C++ 最佳实践的。
  • 条件判断逻辑:在 ensureOsVersion() 中,引入了 #ifndef OS_VERSION_TEST_FILE 预处理指令,使得在测试环境下总是重新读取文件,而在生产环境下则利用缓存。这种逻辑是合理的,能够兼顾测试灵活性和生产环境性能。

2. 代码质量

  • 可读性:代码结构清晰,互斥锁的引入位置明确,易于理解。
  • 命名规范:变量名如 mutex 符合常规命名习惯,但可以考虑更具描述性的名称,如 m_dataMutexm_cacheMutex,以明确其用途。
  • 注释:建议在 mutex 成员变量上方添加注释,说明该锁保护哪些数据成员,例如:
    // 保护 deepinType, osBuild, productType 等缓存数据的线程安全
    mutable QMutex mutex;

3. 代码性能

  • 锁的粒度:目前锁的粒度是整个函数(如 ensureDeepinInfo()),这可能会在高并发场景下成为性能瓶颈。如果函数中有不涉及共享数据的操作,可以考虑缩小锁的范围。例如:
    void DSysInfoPrivate::ensureDeepinInfo()
    {
        // 先检查是否需要加锁
        if (static_cast<int>(deepinType) > 0 && !inTest())
            return;
    
        QMutexLocker locker(&mutex);
        // 再次检查,防止在等待锁的过程中其他线程已经更新了数据
        if (static_cast<int>(deepinType) > 0 && !inTest())
            return;
    
        // 原有逻辑...
    }
    这种“双重检查锁定”模式可以减少不必要的锁竞争。

4. 代码安全

  • 死锁风险:目前代码中没有明显的死锁风险,因为每个函数只持有一个锁,且没有嵌套锁的情况。但如果未来扩展功能时引入多个锁,需要特别注意锁的顺序,避免死锁。
  • 线程安全:引入互斥锁后,deepinTypeosBuildproductType 等成员变量的读写操作现在是线程安全的。但需要确保所有对这些成员变量的访问都通过加锁的函数进行,避免直接访问导致数据竞争。
  • 测试环境下的安全性:在 ensureOsVersion() 中,测试环境下总是重新读取文件,这可能会导致测试结果不一致。建议明确测试环境的线程安全策略,例如是否允许测试环境下并发访问。

改进建议

  1. 双重检查锁定:在 ensureDeepinInfo()ensureOsVersion() 中,可以采用双重检查锁定模式,减少锁竞争。
  2. 更细粒度的锁:如果不同成员变量的访问模式差异较大,可以考虑使用多个互斥锁分别保护不同的数据,以提高并发性能。
  3. 文档化锁的用途:在代码中明确注释每个互斥锁保护的数据成员,方便后续维护。
  4. 测试环境策略:明确测试环境下的线程安全策略,避免测试结果不一致。

改进后的代码示例

void DSysInfoPrivate::ensureDeepinInfo()
{
    // 第一次检查,避免不必要的锁
    if (static_cast<int>(deepinType) > 0 && !inTest())
        return;

    QMutexLocker locker(&mutex);
    // 第二次检查,防止在等待锁时其他线程已经更新了数据
    if (static_cast<int>(deepinType) > 0 && !inTest())
        return;

    // 原有逻辑...
}

总结

这段代码通过引入互斥锁有效地解决了多线程环境下的数据竞争问题,但在性能优化和代码文档化方面还有改进空间。建议采用双重检查锁定模式,并明确锁的用途,以提高代码的并发性能和可维护性。

@deepin-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: 18202781743, mhduiy

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@18202781743 18202781743 merged commit 9650bbc into linuxdeepin:master Feb 5, 2026
17 of 19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants