feat(shared-runtime)!: use weak waker in trigger [APMSP-3371]#2050
feat(shared-runtime)!: use weak waker in trigger [APMSP-3371]#2050VianneyRuhlmann wants to merge 7 commits into
Conversation
📚 Documentation Check Results📦
|
🎉 All green!🧪 All tests passed 🎯 Code Coverage (details) 🔗 Commit SHA: fb940b8 | Docs | Datadog PR Page | Give us feedback! |
🔒 Cargo Deny Results📦
|
Co-authored-by: paullegranddc <82819397+paullegranddc@users.noreply.github.com>
c8bba74 to
28fc7ca
Compare
Clippy Allow Annotation ReportComparing clippy allow annotations between branches:
Summary by Rule
Annotation Counts by File
Annotation Stats by Crate
About This ReportThis report tracks Clippy allow annotations for specific rules, showing how they've changed in this PR. Decreasing the number of these annotations generally improves code quality. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2050 +/- ##
==========================================
+ Coverage 72.93% 73.15% +0.22%
==========================================
Files 460 461 +1
Lines 76711 76769 +58
==========================================
+ Hits 55948 56162 +214
+ Misses 20763 20607 -156
🚀 New features to boost your workflow:
|
Artifact Size Benchmark Reportaarch64-alpine-linux-musl
aarch64-unknown-linux-gnu
libdatadog-x64-windows
libdatadog-x86-windows
x86_64-alpine-linux-musl
x86_64-unknown-linux-gnu
|
yannham
left a comment
There was a problem hiding this comment.
This solution adds a bit of code but looks more robust than the draining channel/on_pause business, is still reasonable and 👍 for the very clear documentation of the weak_waker module
| /// | ||
| /// See the [module-level documentation](self) for details. | ||
| #[must_use = "futures do nothing unless you `.await` or poll them"] | ||
| pub fn wrap<F: Future>(fut: F) -> WeakWakerFuture<F> { |
There was a problem hiding this comment.
Nit: should this be WeakWakerFuture::new, or at least WeakWakerFuture::wrap instead?
|
|
||
| pub struct WeakWakerFuture<F: Future> { | ||
| fut: F, | ||
| weak_waker: Option<WeakWaker>, |
There was a problem hiding this comment.
Naive question: isn't there a double Option wrapping here? If AtomicWaker is already morally an Option<Waker>, could we just use WeakWaker here and put "none" in the atomic waker?
There was a problem hiding this comment.
This is an optimisation so that we never allocate a WeakWaker of the Future is never polled. (A race bewteen two futures with one already ready for instance).
The Option doesn't cost anything since WeakWaker is a wrapper over Arc
There was a problem hiding this comment.
You're right I can remove it, it makes the code way more readable. However it means I have to allocate the WeakWaker Arc and the AtomicWaker in new rather than on the first call to poll, but I think it's worth it.
There was a problem hiding this comment.
Ah, there's an Arc in between indeed. Not sure what's the optimal trade-off, I guess it depends if you expect the "no allocation" case to happen often. I personally don't have a strong opinion
What does this PR do?
Wrap the trigger future waker to use a weak reference on the runtime. This allows the runtime to be dropped and properly shutdown when calling
before_forkMotivation
When reading from a channel in the trigger method, the waker being held by the channel can prevent the tokio driver from being dropped when calling
before_forkwhich can cause crashes in macos as the kqueue handle becomes invalid in the child process.Additional Notes
Anything else we should know when reviewing?
How to test the change?
Describe here in detail how the change can be validated.