Document that `Future` callbacks are not reentrant-safe
What changed, and why it matters
This commit only adds documentation comments warning that callbacks registered on a Future object must not re-enter the same Future or its Notifier. It does not change any code behavior, fix a bug, or add safeguards. The change suggests a pre-existing reentrancy hazard exists, but it is left unfixed because the authors considered it hard to address and not worth the effort.
Treat this as a known API contract hazard rather than a patched vulnerability. If using these callbacks, ensure they never call back into the same Future/Notifier. Consider adding runtime reentrancy guards or refactoring callback dispatch to release the lock before invocation if the project later decides to mitigate.
Security signals we found
Reentrancy safety warning added to public API documentation
Mutex-protected callback invocation without reentrancy guard
Authors explicitly chose not to implement a fix
Evidence from the diff
The diff adds two identical doc comments to register_callback and register_callback_fn in lightning/src/util/wakers.rs, stating that callbacks must not reenter the Future or Notifier. The underlying code still invokes the callback while holding self.state.lock().unwrap(), so reentrant access from within the callback would attempt to acquire the same mutex and panic (Rust std mutex is not reentrant). This is a documentation-only commit; no code path is modified.
Changed components
lightning/src/util/wakers.rsFuture::register_callbackFuture::register_callback_fnNotifierInspect captured patch +4 / −0
diff --git a/lightning/src/util/wakers.rs b/lightning/src/util/wakers.rs
index 17edadf..1a0f08b 100644
--- a/lightning/src/util/wakers.rs
+++ b/lightning/src/util/wakers.rs
@@ -165,6 +165,8 @@ impl Future {
/// Registers a callback to be called upon completion of this future. If the future has already
/// completed, the callback will be called immediately.
///
+ /// Note that callbacks *must not* reenter this [`Future`] or the corresponding [`Notifier`].
+ ///
/// This is not exported to bindings users, use the bindings-only `register_callback_fn` instead
pub fn register_callback(&self, callback: Box<dyn FutureCallback>) {
let mut state = self.state.lock().unwrap();
@@ -182,6 +184,8 @@ impl Future {
// here.
/// Registers a callback to be called upon completion of this future. If the future has already
/// completed, the callback will be called immediately.
+ ///
+ /// Note that callbacks *must not* reenter this [`Future`] or the corresponding [`Notifier`].
#[cfg(c_bindings)]
pub fn register_callback_fn<F: 'static + FutureCallback>(&self, callback: F) {
self.register_callback(Box::new(callback));
Why this scored 26/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.