Skip to content

fix: Separate DConfig object creation to another thread to avoid blocking#548

Merged
zccrs merged 1 commit intolinuxdeepin:masterfrom
calsys456:master
Sep 11, 2025
Merged

fix: Separate DConfig object creation to another thread to avoid blocking#548
zccrs merged 1 commit intolinuxdeepin:masterfrom
calsys456:master

Conversation

@calsys456
Copy link
Collaborator

@calsys456 calsys456 commented Sep 8, 2025

DConfig object creation involves D-Bus communication, which may block when placed in the main thread. This commit adapt dconfig2cpp tool to generate DConfig wrapper safely running in another thread, to avoid this problem.

更新:彻底删除旧的TreelandConfig封装类,将dconfig2cpp生成的类命名为TreelandConfig取而代之。同时将旧有的与工作区相关的本地配置单独拆分为WorkspaceConfig。

Summary by Sourcery

Prevent blocking in the main thread during DConfig creation by moving initialization into a worker thread via a DConfig wrapper generated at build time and synchronously waiting for readiness.

Enhancements:

  • Offload DConfig initialization to a background thread using the generated dconfig_org_deepin_treeland wrapper
  • Block the TreelandConfig constructor on a QEventLoop until configInitializeSucceed emits an 'initialized' signal

Build:

  • Add dtk_add_config_to_cpp in CMake to generate and compile dconfig_org_deepin_treeland.hpp using the org.deepin.treeland schema
  • Expand Dtk6 find_package call to include Tools component and include the generated DConfig wrapper in libtreeland

Chores:

  • Update Nix and Debian packaging to add deepin.dtk6core as a runtime dependency

@deepin-ci-robot
Copy link

Hi @apr3vau. Thanks for your PR.

I'm waiting for a linuxdeepin member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@sourcery-ai
Copy link

sourcery-ai bot commented Sep 8, 2025

Reviewer's Guide

This PR avoids blocking the main thread by moving DConfig setup into a background context via a dconfig2cpp-generated wrapper, synchronizing initialization with a QEventLoop and signals; it also updates the CMake build to generate and include the wrapper header and adjusts packaging dependencies accordingly.

Sequence diagram for asynchronous DConfig initialization in TreelandConfig

sequenceDiagram
    participant TreelandConfig
    participant dconfig_org_deepin_treeland
    participant QEventLoop
    TreelandConfig->>dconfig_org_deepin_treeland: createByName()
    TreelandConfig->>QEventLoop: connect initialized signal
    dconfig_org_deepin_treeland-->>TreelandConfig: configInitializeSucceed signal
    TreelandConfig->>TreelandConfig: Assign DConfig and read values
    TreelandConfig->>TreelandConfig: emit initialized()
    TreelandConfig->>QEventLoop: quit()
    QEventLoop->>QEventLoop: exec() (waits for initialized)
    TreelandConfig->>DConfig: connect valueChanged signal
Loading

Class diagram for updated TreelandConfig and dconfig_org_deepin_treeland integration

classDiagram
    class TreelandConfig {
        +initialized()
        -dconfig_org_deepin_treeland *
        -std::unique_ptr<DConfig> m_dconfig
        -uint m_maxWorkspace
        -uint m_numWorkspace
        -uint m_currentWorkspace
        -bool m_forceSoftwareCursor
        -QString m_activeColor
        -float m_windowRadius
        -QString m_cursorThemeName
        -QSize m_cursorSize
        -uint m_windowOpacity
        -uint m_windowThemeType
        -uint m_windowTitlebarHeight
        -QString m_fontName
        -QString m_monoFontName
        -uint m_fontSize
        -QString m_iconThemeName
        -QString m_defaultBackground
        +onDConfigChanged(key: QString)
    }
    class dconfig_org_deepin_treeland {
        +createByName(name: QString, service: QString, path: QString)
        +configInitializeSucceed
        +config(): DConfig*
    }
    TreelandConfig --> dconfig_org_deepin_treeland : uses
    TreelandConfig --> DConfig : owns
Loading

File-Level Changes

Change Details Files
Offload DConfig instantiation to a separate thread using the dconfig2cpp wrapper
  • Replaced direct DConfig::create calls with dconfig_org_deepin_treeland::createByName
  • Introduced QEventLoop and connected initialized/configInitializeSucceed signals to await setup
  • Moved all DConfig value assignments into the configInitializeSucceed handler and emit initialized()
src/config/treelandconfig.cpp
src/config/treelandconfig.h
Integrate dconfig2cpp code generation into the build process
  • Added Tools component to find_package(Dtk6)
  • Added dtk_add_config_to_cpp call to generate dconfig_org_deepin_treeland.hpp
  • Included the generated DConfig wrapper in the qt_add_qml_module sources
src/CMakeLists.txt
Update packaging dependencies for the new DConfig wrapper
  • Added deepin.dtk6core to Nix build inputs
nix/default.nix

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes and found some issues that need to be addressed.

Blocking issues:

  • Blocking the constructor with QEventLoop may cause deadlocks or UI freezes. (link)

General comments:

  • Consider adding error handling for config initialization failures (e.g., handling the configInitializeFailed signal) to avoid the event loop hanging indefinitely if initialization fails.
  • Avoid blocking in the constructor with a QEventLoop—consider exposing asynchronous initialization or using a factory method to initialize TreelandConfig, which can improve responsiveness and avoid potential deadlocks.
  • Rather than storing the raw pointer m_dconfig_org_deepin_treeland, consider transferring ownership with a smart pointer (e.g., QScopedPointer or std::unique_ptr) to ensure proper cleanup and avoid memory leaks.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Consider adding error handling for config initialization failures (e.g., handling the configInitializeFailed signal) to avoid the event loop hanging indefinitely if initialization fails.
- Avoid blocking in the constructor with a QEventLoop—consider exposing asynchronous initialization or using a factory method to initialize TreelandConfig, which can improve responsiveness and avoid potential deadlocks.
- Rather than storing the raw pointer m_dconfig_org_deepin_treeland, consider transferring ownership with a smart pointer (e.g., QScopedPointer or std::unique_ptr) to ensure proper cleanup and avoid memory leaks.

## Individual Comments

### Comment 1
<location> `src/config/treelandconfig.cpp:16` </location>
<code_context>
+    QEventLoop eventLoop;
</code_context>

<issue_to_address>
Blocking the constructor with QEventLoop may cause deadlocks or UI freezes.

Blocking the main thread in a constructor with QEventLoop::exec() risks deadlocks and UI unresponsiveness. Refactor to initialize asynchronously or defer setup until after construction.
</issue_to_address>

### Comment 2
<location> `src/config/treelandconfig.cpp:44` </location>
<code_context>
+            });
+    eventLoop.exec();
+
     connect(m_dconfig.get(), &DConfig::valueChanged, this, &TreelandConfig::onDConfigChanged);
 }

</code_context>

<issue_to_address>
Connecting to m_dconfig before it is initialized may cause runtime errors.

If configInitializeSucceed is not emitted, m_dconfig remains null, which can cause a crash. Please ensure m_dconfig is valid before connecting, or add a guard to prevent this issue.
</issue_to_address>

### Comment 3
<location> `src/config/treelandconfig.cpp:40` </location>
<code_context>
+                m_fontSize = m_dconfig->value("fontSize", 105).toUInt();
+                m_iconThemeName = m_dconfig->value("iconThemeName").toString();
+                m_defaultBackground = m_dconfig->value("defaultBackground").toString();
+                Q_EMIT initialized();
+            });
+    eventLoop.exec();
</code_context>

<issue_to_address>
Emitting initialized() inside a lambda may cause reentrancy issues.

Consider emitting the signal after object construction or adding safeguards to prevent slots from accessing the object before it is fully initialized.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@calsys456 calsys456 force-pushed the master branch 2 times, most recently from bb4e496 to 0da3db9 Compare September 10, 2025 03:15
@wineee wineee mentioned this pull request Sep 10, 2025
@calsys456 calsys456 force-pushed the master branch 2 times, most recently from 0da3db9 to 796d461 Compare September 11, 2025 05:27
…king

DConfig object creation involves D-Bus communication, which may block
when placed in the main thread. This commit adapt dconfig2cpp tool to
generate DConfig wrapper safely running in another thread, to avoid this
problem.
@zccrs zccrs merged commit fa1e1e6 into linuxdeepin:master Sep 11, 2025
6 checks passed
@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: apr3vau, zccrs

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants