Skip to content

Add is_alive method to CxxQtThread #984

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Oct 4, 2024

Conversation

akiselev
Copy link
Contributor

When combining async Rust channels and QT objects, it's really easy to end up in a situation where a message is received on the channel after the QObject has already been destroyed, causing CxxQtThread::queue to throw an exception. This PR introduces an is_alive() function to check the handle if it's been invalidated.

  • Implement is_alive method in C++ CxxQtThread class
  • Add is_alive to Rust Threading trait
  • Generate FFI bindings for is_alive in cxx-qt-gen
  • Expose is_alive as a public method on CxxQtThread in Rust
  • Update documentation for Threading trait and CxxQtThread

@LeonMatthesKDAB
Copy link
Collaborator

Hi @akiselev , thank you for taking the time to create this PR!

overall I think the is_alive method should be useful, so it's good to have it.
However, depending on what you want to use it for, this may not do what you intend!

If you want to check is_alive before calling queue, this will not work!

e.g. this:

if thread.is_alive() {
    thread.queue(...).unwrap()
}

May panic and crash your program. The reason for this is that the CxxQtThread does not have ownership of the QObject, it is only a handle to the thread the QObject lives in.
That other thread may delete the QObject at any time, including between the calls to is_alive() and queue.

So ideally you should really prefer just using.

thread.queue(...).ok();

if you want to avoid crashing your application in that case.

If however, you want to use is_alive() to e.g. exit a loop:

while qobject_thread.is_alive() {
    // do some rust work
    // maybe message the qobject somewhere
    qobject_thread.queue(...).ok();
    // do some more rust work
}

Then it's very much a good and convenient API.

So really you can only know for certain whether a QObject has already been destroyed, not whether it's still alive, as it may be destroyed at any point.
Therefore I'd suggest renaming this to is_destructed/is_destroyed/is_dead or something like this and prominently documenting this caveat.

@akiselev
Copy link
Contributor Author

I renamed the method to is_destroyed and added a better doc comment explaining the race condition

@LeonMatthesKDAB
Copy link
Collaborator

Hi @akiselev , Thank you for the update to the PR.
I'm happy to approve the new API, but suspect CI will fail because the tests haven't been updated to the new generated output.
If your system supports it, can you run the ./update_expected.sh shell script in the cxx-qt-gen directory?
That should automatically update the generation tests.

In case you have issues with the script, I can run it as well, just let me know.

@akiselev
Copy link
Contributor Author

Updated

@ahayzen-kdab
Copy link
Collaborator

Looks there there is another case of a test needing updating :-)

Note you can run cargo test in the crates/cxx-qt-gen to see the ones that are failing.

Copy link

codecov bot commented Oct 4, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 100.00%. Comparing base (f366fcb) to head (9be9362).

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #984   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           71        71           
  Lines        11928     11953   +25     
=========================================
+ Hits         11928     11953   +25     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@LeonMatthesKDAB
Copy link
Collaborator

I updated the tests, so they hopefully pass CI now.

akiselev and others added 4 commits October 4, 2024 09:28
- Implement is_destroyed method for CxxQtThread to check if associated QObject has been destroyed
- Add cxxQtThreadIsDestroyed function in C++ header
- Update Rust trait and implementation for Threading
- Add documentation explaining usage and potential race conditions
- Modify code generation to include new method in FFI layer
@ahayzen-kdab ahayzen-kdab enabled auto-merge (squash) October 4, 2024 08:29
Copy link
Collaborator

@ahayzen-kdab ahayzen-kdab left a comment

Choose a reason for hiding this comment

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

LGTM :-)

@ahayzen-kdab ahayzen-kdab merged commit 85526ac into KDAB:main Oct 4, 2024
15 checks passed
@LeonMatthesKDAB
Copy link
Collaborator

Great to see this finally merged.

Thank you @akiselev for your contribution!

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.

3 participants