@@ -166,7 +166,7 @@ impl UtxoFuture {
166166}
167167
168168struct PendingChecksContext {
169- channels : HashMap < u64 , Weak < Mutex < UtxoMessages > > > ,
169+ channels : HashMap < u64 , Arc < Mutex < UtxoMessages > > > ,
170170 nodes : HashMap < NodeId , Vec < Weak < Mutex < UtxoMessages > > > > ,
171171}
172172
@@ -194,9 +194,13 @@ impl PendingChecks {
194194 ) -> Result < ( ) , LightningError > {
195195 let mut pending_checks = self . internal . lock ( ) . unwrap ( ) ;
196196 if let hash_map:: Entry :: Occupied ( e) = pending_checks. channels . entry ( msg. short_channel_id ) {
197- let is_from_a = ( msg. channel_flags & 1 ) == 1 ;
198- match Weak :: upgrade ( e. get ( ) ) {
199- Some ( msgs_ref) => {
197+ if Arc :: strong_count ( e. get ( ) ) == 1 {
198+ // The future was dropped and the entry is the last reference held.
199+ e. remove ( ) ;
200+ } else {
201+ let is_from_a = ( msg. channel_flags & 1 ) == 1 ;
202+ {
203+ let msgs_ref = e. get ( ) ;
200204 let mut messages = msgs_ref. lock ( ) . unwrap ( ) ;
201205 let latest_update = if is_from_a {
202206 & mut messages. latest_channel_update_a
@@ -216,15 +220,12 @@ impl PendingChecks {
216220 ChannelUpdate :: Unsigned ( msg. clone ( ) )
217221 } ) ;
218222 }
219- return Err ( LightningError {
220- err : "Awaiting channel_announcement validation to accept channel_update"
221- . to_owned ( ) ,
222- action : ErrorAction :: IgnoreAndLog ( Level :: Gossip ) ,
223- } ) ;
224- } ,
225- None => {
226- e. remove ( ) ;
227- } ,
223+ }
224+ return Err ( LightningError {
225+ err : "Awaiting channel_announcement validation to accept channel_update"
226+ . to_owned ( ) ,
227+ action : ErrorAction :: IgnoreAndLog ( Level :: Gossip ) ,
228+ } ) ;
228229 }
229230 }
230231 Ok ( ( ) )
@@ -284,22 +285,31 @@ impl PendingChecks {
284285
285286 fn check_replace_previous_entry (
286287 msg : & msgs:: UnsignedChannelAnnouncement , full_msg : Option < & msgs:: ChannelAnnouncement > ,
287- replacement : Option < Weak < Mutex < UtxoMessages > > > ,
288- pending_channels : & mut HashMap < u64 , Weak < Mutex < UtxoMessages > > > ,
288+ replacement : Option < Arc < Mutex < UtxoMessages > > > ,
289+ pending_channels : & mut HashMap < u64 , Arc < Mutex < UtxoMessages > > > ,
289290 ) -> Result < ( ) , msgs:: LightningError > {
290291 match pending_channels. entry ( msg. short_channel_id ) {
291292 hash_map:: Entry :: Occupied ( mut e) => {
292- // There's already a pending lookup for the given SCID. Check if the messages
293- // are the same and, if so, return immediately (don't bother spawning another
294- // lookup if we haven't gotten that far yet).
295- match Weak :: upgrade ( & e. get ( ) ) {
296- Some ( pending_msgs) => {
297- // This may be called with the mutex held on a different UtxoMessages
298- // struct, however in that case we have a global lockorder of new messages
299- // -> old messages, which makes this safe.
300- let pending_matches = match & pending_msgs
301- . unsafe_well_ordered_double_lock_self ( )
302- . channel_announce
293+ if Arc :: strong_count ( e. get ( ) ) == 1 {
294+ // The future was dropped and the entry is the last reference held.
295+ //
296+ // The earlier lookup already resolved. We can't be sure its the same
297+ // so just remove/replace it and move on.
298+ if let Some ( item) = replacement {
299+ * e. get_mut ( ) = item;
300+ } else {
301+ e. remove ( ) ;
302+ }
303+ } else {
304+ // There's already a pending lookup for the given SCID. Check if the messages
305+ // are the same and, if so, return immediately (don't bother spawning another
306+ // lookup if we haven't gotten that far yet).
307+ let pending_msgs = e. get ( ) ;
308+ // This may be called with the mutex held on a different UtxoMessages
309+ // struct, however in that case we have a global lockorder of new messages
310+ // -> old messages, which makes this safe.
311+ let pending_matches =
312+ match & pending_msgs. unsafe_well_ordered_double_lock_self ( ) . channel_announce
303313 {
304314 Some ( ChannelAnnouncement :: Full ( pending_msg) ) => {
305315 Some ( pending_msg) == full_msg
@@ -314,31 +324,21 @@ impl PendingChecks {
314324 false
315325 } ,
316326 } ;
317- if pending_matches {
318- return Err ( LightningError {
319- err : "Channel announcement is already being checked" . to_owned ( ) ,
320- action : ErrorAction :: IgnoreDuplicateGossip ,
321- } ) ;
322- } else {
323- // The earlier lookup is a different message. If we have another
324- // request in-flight now replace the original.
325- // Note that in the replace case whether to replace is somewhat
326- // arbitrary - both results will be handled, we're just updating the
327- // value that will be compared to future lookups with the same SCID.
328- if let Some ( item) = replacement {
329- * e. get_mut ( ) = item;
330- }
331- }
332- } ,
333- None => {
334- // The earlier lookup already resolved. We can't be sure its the same
335- // so just remove/replace it and move on.
327+ if pending_matches {
328+ return Err ( LightningError {
329+ err : "Channel announcement is already being checked" . to_owned ( ) ,
330+ action : ErrorAction :: IgnoreDuplicateGossip ,
331+ } ) ;
332+ } else {
333+ // The earlier lookup is a different message. If we have another
334+ // request in-flight now replace the original.
335+ // Note that in the replace case whether to replace is somewhat
336+ // arbitrary - both results will be handled, we're just updating the
337+ // value that will be compared to future lookups with the same SCID.
336338 if let Some ( item) = replacement {
337339 * e. get_mut ( ) = item;
338- } else {
339- e. remove ( ) ;
340340 }
341- } ,
341+ }
342342 }
343343 } ,
344344 hash_map:: Entry :: Vacant ( v) => {
@@ -416,7 +416,7 @@ impl PendingChecks {
416416 Self :: check_replace_previous_entry (
417417 msg,
418418 full_msg,
419- Some ( Arc :: downgrade ( & future. state ) ) ,
419+ Some ( Arc :: clone ( & future. state ) ) ,
420420 & mut pending_checks. channels ,
421421 ) ?;
422422 async_messages. channel_announce = Some ( if let Some ( msg) = full_msg {
@@ -464,7 +464,7 @@ impl PendingChecks {
464464 // If we have many channel checks pending, ensure we don't have any dangling checks
465465 // (i.e. checks where the user told us they'd call back but drop'd the `UtxoFuture`
466466 // instead) before we commit to applying backpressure.
467- pending_checks. channels . retain ( |_, chan| Weak :: upgrade ( & chan) . is_some ( ) ) ;
467+ pending_checks. channels . retain ( |_, chan| Arc :: strong_count ( chan) > 1 ) ;
468468 pending_checks. nodes . retain ( |_, channels| {
469469 channels. retain ( |chan| Weak :: upgrade ( & chan) . is_some ( ) ) ;
470470 !channels. is_empty ( )
@@ -575,16 +575,16 @@ impl PendingChecks {
575575 {
576576 let mut lck = self . internal . lock ( ) . unwrap ( ) ;
577577 lck. channels . retain ( |_, state| {
578- if let Some ( state) = state . upgrade ( ) {
579- if state . lock ( ) . unwrap ( ) . complete . is_some ( ) {
580- completed_states . push ( state ) ;
581- false
582- } else {
578+ if state. lock ( ) . unwrap ( ) . complete . is_some ( ) {
579+ completed_states . push ( Arc :: clone ( & state ) ) ;
580+ false
581+ } else {
582+ if Arc :: strong_count ( & state ) > 1 {
583583 true
584+ } else {
585+ // The UtxoFuture has been dropped, drop the pending-lookup state.
586+ false
584587 }
585- } else {
586- // The UtxoFuture has been dropped, drop the pending-lookup state.
587- false
588588 }
589589 } ) ;
590590 lck. nodes . retain ( |_, lookups| {
0 commit comments