Skip to content

Commit e36abb7

Browse files
authored
Merge pull request #3943 from TheBlueMatt/2024-09-async-persist-claiming-from-closed-chan
Restore debug assertion removed due to lockorder restrictions
2 parents 4e4f128 + eadb70f commit e36abb7

File tree

4 files changed

+78
-6
lines changed

4 files changed

+78
-6
lines changed

lightning-liquidity/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
#![allow(ellipsis_inclusive_range_patterns)]
4747
#![allow(clippy::drop_non_drop)]
4848
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
49-
#![cfg_attr(not(feature = "std"), no_std)]
49+
#![cfg_attr(not(any(test, feature = "std")), no_std)]
5050

5151
#[macro_use]
5252
extern crate alloc;

lightning/src/ln/channelmanager.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8340,6 +8340,8 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
83408340
hold_time,
83418341
);
83428342

8343+
#[cfg(test)]
8344+
let claiming_chan_funding_outpoint = hop_data.outpoint;
83438345
self.claim_funds_from_hop(
83448346
hop_data,
83458347
payment_preimage,
@@ -8358,6 +8360,50 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
83588360
// monitor updates still in flight. In that case, we shouldn't
83598361
// immediately free, but instead let that monitor update complete
83608362
// in the background.
8363+
#[cfg(test)]
8364+
{
8365+
let per_peer_state = self.per_peer_state.deadlocking_read();
8366+
// The channel we'd unblock should already be closed, or...
8367+
let channel_closed = per_peer_state
8368+
.get(&next_channel_counterparty_node_id)
8369+
.map(|lck| lck.deadlocking_lock())
8370+
.map(|peer| !peer.channel_by_id.contains_key(&next_channel_id))
8371+
.unwrap_or(true);
8372+
let background_events =
8373+
self.pending_background_events.lock().unwrap();
8374+
// there should be a `BackgroundEvent` pending...
8375+
let matching_bg_event =
8376+
background_events.iter().any(|ev| {
8377+
match ev {
8378+
// to apply a monitor update that blocked the claiming channel,
8379+
BackgroundEvent::MonitorUpdateRegeneratedOnStartup {
8380+
funding_txo, update, ..
8381+
} => {
8382+
if *funding_txo == claiming_chan_funding_outpoint {
8383+
assert!(update.updates.iter().any(|upd|
8384+
if let ChannelMonitorUpdateStep::PaymentPreimage {
8385+
payment_preimage: update_preimage, ..
8386+
} = upd {
8387+
payment_preimage == *update_preimage
8388+
} else { false }
8389+
), "{:?}", update);
8390+
true
8391+
} else { false }
8392+
},
8393+
// or the monitor update has completed and will unblock
8394+
// immediately once we get going.
8395+
BackgroundEvent::MonitorUpdatesComplete {
8396+
channel_id, ..
8397+
} =>
8398+
*channel_id == prev_channel_id,
8399+
}
8400+
});
8401+
assert!(
8402+
channel_closed || matching_bg_event,
8403+
"{:?}",
8404+
*background_events
8405+
);
8406+
}
83618407
(None, None)
83628408
} else if definitely_duplicate {
83638409
if let Some(other_chan) = chan_to_release {

lightning/src/sync/debug_sync.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
pub use alloc::sync::Arc;
22
use core::fmt;
33
use core::ops::{Deref, DerefMut};
4+
#[cfg(feature = "std")]
45
use core::time::Duration;
56

67
use std::cell::RefCell;
@@ -10,6 +11,7 @@ use std::sync::RwLock as StdRwLock;
1011
use std::sync::RwLockReadGuard as StdRwLockReadGuard;
1112
use std::sync::RwLockWriteGuard as StdRwLockWriteGuard;
1213

14+
#[cfg(feature = "std")]
1315
use parking_lot::Condvar as StdCondvar;
1416
use parking_lot::Mutex as StdMutex;
1517
use parking_lot::MutexGuard as StdMutexGuard;
@@ -34,10 +36,12 @@ impl Backtrace {
3436

3537
pub type LockResult<Guard> = Result<Guard, ()>;
3638

39+
#[cfg(feature = "std")]
3740
pub struct Condvar {
3841
inner: StdCondvar,
3942
}
4043

44+
#[cfg(feature = "std")]
4145
impl Condvar {
4246
pub fn new() -> Condvar {
4347
Condvar { inner: StdCondvar::new() }
@@ -287,6 +291,7 @@ pub struct MutexGuard<'a, T: Sized + 'a> {
287291
}
288292

289293
impl<'a, T: Sized> MutexGuard<'a, T> {
294+
#[cfg(feature = "std")]
290295
fn into_inner(self) -> StdMutexGuard<'a, T> {
291296
// Somewhat unclear why we cannot move out of self.lock, but doing so gets E0509.
292297
unsafe {
@@ -332,6 +337,19 @@ impl<T> Mutex<T> {
332337
}
333338
}
334339

340+
#[cfg(test)]
341+
/// Takes a lock without any deadlock detection logic. This should never exist in production
342+
/// code (the deadlock detection logic is important!) but can be used in tests where we're
343+
/// willing to risk deadlocks (accepting that simply no existing tests hit them).
344+
pub fn deadlocking_lock<'a>(&'a self) -> MutexGuard<'a, T> {
345+
let lock = self.inner.lock();
346+
if self.poisoned.load(Ordering::Acquire) {
347+
panic!();
348+
} else {
349+
MutexGuard { mutex: self, lock: Some(lock) }
350+
}
351+
}
352+
335353
pub fn lock<'a>(&'a self) -> LockResult<MutexGuard<'a, T>> {
336354
LockMetadata::pre_lock(&self.deps, false);
337355
let lock = self.inner.lock();
@@ -443,6 +461,14 @@ impl<T> RwLock<T> {
443461
self.inner.read().map(|guard| RwLockReadGuard { lock: self, guard }).map_err(|_| ())
444462
}
445463

464+
#[cfg(test)]
465+
/// Takes a read lock without any deadlock detection logic. This should never exist in
466+
/// production code (the deadlock detection logic is important!) but can be used in tests where
467+
/// we're willing to risk deadlocks (accepting that simply no existing tests hit them).
468+
pub fn deadlocking_read<'a>(&'a self) -> RwLockReadGuard<'a, T> {
469+
self.inner.read().map(|guard| RwLockReadGuard { lock: self, guard }).unwrap()
470+
}
471+
446472
pub fn write<'a>(&'a self) -> LockResult<RwLockWriteGuard<'a, T>> {
447473
LockMetadata::pre_lock(&self.deps, false);
448474
self.inner.write().map(|guard| RwLockWriteGuard { lock: self, guard }).map_err(|_| ())

lightning/src/sync/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ pub(crate) trait LockTestExt<'a> {
2020
fn unsafe_well_ordered_double_lock_self(&'a self) -> Self::ExclLock;
2121
}
2222

23-
#[cfg(all(feature = "std", not(ldk_bench), test))]
23+
#[cfg(all(not(ldk_bench), test))]
2424
mod debug_sync;
25-
#[cfg(all(feature = "std", not(ldk_bench), test))]
25+
#[cfg(all(not(ldk_bench), test))]
2626
pub use debug_sync::*;
27-
#[cfg(all(feature = "std", not(ldk_bench), test))]
27+
#[cfg(all(not(ldk_bench), test))]
2828
// Note that to make debug_sync's regex work this must not contain `debug_string` in the module name
2929
mod test_lockorder_checks;
3030

@@ -63,7 +63,7 @@ mod ext_impl {
6363
}
6464
}
6565

66-
#[cfg(not(feature = "std"))]
66+
#[cfg(all(not(feature = "std"), any(ldk_bench, not(test))))]
6767
mod nostd_sync;
68-
#[cfg(not(feature = "std"))]
68+
#[cfg(all(not(feature = "std"), any(ldk_bench, not(test))))]
6969
pub use nostd_sync::*;

0 commit comments

Comments
 (0)