apache / celix

Apache Celix is a framework for C and C++14 to develop dynamic modular software applications using component and in-process service-oriented programming.
https://celix.apache.org/
Apache License 2.0
165 stars 86 forks source link

Feature/215 async-signal-safe launcher shutdown #753

Closed PengZheng closed 3 months ago

PengZheng commented 3 months ago

This PR fixes a long-standing issue #215 by implementing async-signal-safe launcher shutdown. Without making our event loop more powerful (like libuv), I think setting a flag to be checked by a periodic scheduled event callback is the best we can do. So here it is.

This PR also makes celix_launcher_triggerStop safer. Previously a bundle may initiate a framework shutdown, which will cause celix_framework_waitForStop to return without noticing the launcher. In that case, celix_launcher_triggerStop might reference a to-be-destroyed framework instance to wreck havoc. Now we prevent it from happening with g_launcher.lock.

codecov-commenter commented 3 months ago

Codecov Report

All modified and coverable lines are covered by tests :white_check_mark:

Project coverage is 90.31%. Comparing base (58860bb) to head (2378bac).

Additional details and impacted files ```diff @@ Coverage Diff @@ ## master #753 +/- ## ========================================== + Coverage 90.24% 90.31% +0.06% ========================================== Files 226 226 Lines 26284 26316 +32 ========================================== + Hits 23721 23767 +46 + Misses 2563 2549 -14 ```

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

PengZheng commented 3 months ago

Here is an interesting program hang: https://github.com/apache/celix/actions/runs/9478654947/job/26115518903

Warning: 12T08:29:26] [warning] [celix_framework] [celix_scheduledEvent_waitForRemoved:237] Timeout while waiting for removal of scheduled event 'celix_shutdown_check' (id=0) for bundle id 0.
Warning: 12T08:29:28] [warning] [celix_framework] [celix_scheduledEvent_waitForRemoved:237] Timeout while waiting for removal of scheduled event 'celix_shutdown_check' (id=0) for bundle id 0.
Warning: 12T08:29:30] [warning] [celix_framework] [celix_scheduledEvent_waitForRemoved:237] Timeout while waiting for removal of scheduled event 'celix_shutdown_check' (id=0) for bundle id 0.
Warning: 12T08:29:32] [warning] [celix_framework] [celix_scheduledEvent_waitForRemoved:237] Timeout while waiting for removal of scheduled event 'celix_shutdown_check' (id=0) for bundle id 0.
Warning: 12T08:29:34] [warning] [celix_framework] [celix_scheduledEvent_waitForRemoved:237] Timeout while waiting for removal of scheduled event 'celix_shutdown_check' (id=0) for bundle id 0.

The issue should have been fixed by d384c86. Note that hello_bundle in test_package is a perfect example of framework shutdown initiated by a bundle, which happens to reveal a defect in our scheduled event implementation.

There are still room for further improvements: ideally we shall not permit events (neither generic or scheduled) to be posted to an inactive dispatcher. But I will leave it for a future PR.

pnoltes commented 3 months ago

Without making our event loop more powerful (like libuv), ...

libuv is very interesting and seems to provide a lot of the functionality we use and have implemented ourselves, including a single-thread event loop, shutdown procedure, as well as cross-platform polling, threading, locking, filesystem abstractions, etc. Since it uses an MIT license and does not have dependencies, it could be suitable for Apache Celix.

This could help in supporting more platforms and even be a step towards supporting Windows (we had some support for loading DLL libraries in the past).

In the short term, this may be a step too far, but it's at least worth a discussion. @PengZheng, any thoughts on how feasible it would be to introduce libuv, starting with our file, time, threading, and locking usage/abstractions?

PengZheng commented 3 months ago

@PengZheng, any thoughts on how feasible it would be to introduce libuv, starting with our file, time, threading, and locking usage/abstractions?

libuv is the central piece of an event processing framework used heavily in my day job. I have very positive experience with it, and think it can be useful in the following regards:

Specific to this PR: