fix loose node refs
This commit is contained in:
		@@ -45,6 +45,10 @@ pub struct BucketEntry {
 | 
			
		||||
    peer_stats: PeerStats,
 | 
			
		||||
    latency_stats_accounting: LatencyStatsAccounting,
 | 
			
		||||
    transfer_stats_accounting: TransferStatsAccounting,
 | 
			
		||||
    #[cfg(feature = "tracking")]
 | 
			
		||||
    next_track_id: usize,
 | 
			
		||||
    #[cfg(feature = "tracking")]
 | 
			
		||||
    node_ref_tracks: HashMap<usize, backtrace::Backtrace>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl BucketEntry {
 | 
			
		||||
@@ -57,8 +61,6 @@ impl BucketEntry {
 | 
			
		||||
            last_connection: None,
 | 
			
		||||
            opt_signed_node_info: None,
 | 
			
		||||
            opt_local_node_info: None,
 | 
			
		||||
            latency_stats_accounting: LatencyStatsAccounting::new(),
 | 
			
		||||
            transfer_stats_accounting: TransferStatsAccounting::new(),
 | 
			
		||||
            peer_stats: PeerStats {
 | 
			
		||||
                time_added: now,
 | 
			
		||||
                rpc_stats: RPCStats::default(),
 | 
			
		||||
@@ -66,9 +68,29 @@ impl BucketEntry {
 | 
			
		||||
                transfer: TransferStatsDownUp::default(),
 | 
			
		||||
                status: None,
 | 
			
		||||
            },
 | 
			
		||||
            latency_stats_accounting: LatencyStatsAccounting::new(),
 | 
			
		||||
            transfer_stats_accounting: TransferStatsAccounting::new(),
 | 
			
		||||
            #[cfg(feature = "tracking")]
 | 
			
		||||
            next_track_id: 0,
 | 
			
		||||
            #[cfg(feature = "tracking")]
 | 
			
		||||
            node_ref_tracks: HashMap::new(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(feature = "tracking")]
 | 
			
		||||
    pub fn track(&mut self) -> usize {
 | 
			
		||||
        let track_id = self.next_track_id;
 | 
			
		||||
        self.next_track_id += 1;
 | 
			
		||||
        self.node_ref_tracks
 | 
			
		||||
            .insert(track_id, backtrace::Backtrace::new_unresolved());
 | 
			
		||||
        track_id
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(feature = "tracking")]
 | 
			
		||||
    pub fn untrack(&mut self, track_id: usize) {
 | 
			
		||||
        self.node_ref_tracks.remove(&track_id);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn sort_fastest(e1: &Self, e2: &Self) -> std::cmp::Ordering {
 | 
			
		||||
        // Lower latency to the front
 | 
			
		||||
        if let Some(e1_latency) = &e1.peer_stats.latency {
 | 
			
		||||
@@ -410,6 +432,15 @@ impl BucketEntry {
 | 
			
		||||
impl Drop for BucketEntry {
 | 
			
		||||
    fn drop(&mut self) {
 | 
			
		||||
        if self.ref_count != 0 {
 | 
			
		||||
            #[cfg(feature = "tracking")]
 | 
			
		||||
            {
 | 
			
		||||
                println!("NodeRef Tracking");
 | 
			
		||||
                for (id, bt) in &mut self.node_ref_tracks {
 | 
			
		||||
                    bt.resolve();
 | 
			
		||||
                    println!("Id: {}\n----------------\n{:#?}", id, bt);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            panic!(
 | 
			
		||||
                "bucket entry dropped with non-zero refcount: {:#?}",
 | 
			
		||||
                self.node_info()
 | 
			
		||||
 
 | 
			
		||||
@@ -364,6 +364,29 @@ impl RoutingTable {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn terminate(&self) {
 | 
			
		||||
        // Cancel all tasks being ticked
 | 
			
		||||
        if let Err(e) = self.unlocked_inner.rolling_transfers_task.cancel().await {
 | 
			
		||||
            warn!("rolling_transfers_task not cancelled: {}", e);
 | 
			
		||||
        }
 | 
			
		||||
        if let Err(e) = self.unlocked_inner.bootstrap_task.cancel().await {
 | 
			
		||||
            warn!("bootstrap_task not cancelled: {}", e);
 | 
			
		||||
        }
 | 
			
		||||
        if let Err(e) = self.unlocked_inner.peer_minimum_refresh_task.cancel().await {
 | 
			
		||||
            warn!("peer_minimum_refresh_task not cancelled: {}", e);
 | 
			
		||||
        }
 | 
			
		||||
        if let Err(e) = self.unlocked_inner.ping_validator_task.cancel().await {
 | 
			
		||||
            warn!("ping_validator_task not cancelled: {}", e);
 | 
			
		||||
        }
 | 
			
		||||
        if self
 | 
			
		||||
            .unlocked_inner
 | 
			
		||||
            .node_info_update_single_future
 | 
			
		||||
            .cancel()
 | 
			
		||||
            .await
 | 
			
		||||
            .is_err()
 | 
			
		||||
        {
 | 
			
		||||
            warn!("node_info_update_single_future not cancelled");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        *self.inner.lock() = Self::new_inner(self.network_manager());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,8 @@ pub struct NodeRef {
 | 
			
		||||
    routing_table: RoutingTable,
 | 
			
		||||
    node_id: DHTKey,
 | 
			
		||||
    filter: Option<DialInfoFilter>,
 | 
			
		||||
    #[cfg(feature = "tracking")]
 | 
			
		||||
    track_id: usize,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl NodeRef {
 | 
			
		||||
@@ -20,10 +22,13 @@ impl NodeRef {
 | 
			
		||||
        filter: Option<DialInfoFilter>,
 | 
			
		||||
    ) -> Self {
 | 
			
		||||
        entry.ref_count += 1;
 | 
			
		||||
 | 
			
		||||
        Self {
 | 
			
		||||
            routing_table,
 | 
			
		||||
            node_id: key,
 | 
			
		||||
            filter,
 | 
			
		||||
            #[cfg(feature = "tracking")]
 | 
			
		||||
            track_id: entry.track(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -255,12 +260,15 @@ impl Clone for NodeRef {
 | 
			
		||||
    fn clone(&self) -> Self {
 | 
			
		||||
        self.operate(move |e| {
 | 
			
		||||
            e.ref_count += 1;
 | 
			
		||||
        });
 | 
			
		||||
        Self {
 | 
			
		||||
            routing_table: self.routing_table.clone(),
 | 
			
		||||
            node_id: self.node_id,
 | 
			
		||||
            filter: self.filter.clone(),
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
            Self {
 | 
			
		||||
                routing_table: self.routing_table.clone(),
 | 
			
		||||
                node_id: self.node_id,
 | 
			
		||||
                filter: self.filter.clone(),
 | 
			
		||||
                #[cfg(feature = "tracking")]
 | 
			
		||||
                track_id: e.track(),
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -272,23 +280,25 @@ impl PartialEq for NodeRef {
 | 
			
		||||
 | 
			
		||||
impl Eq for NodeRef {}
 | 
			
		||||
 | 
			
		||||
impl fmt::Display for NodeRef {
 | 
			
		||||
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 | 
			
		||||
        write!(f, "{}", self.node_id.encode())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl fmt::Debug for NodeRef {
 | 
			
		||||
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 | 
			
		||||
        if f.alternate() {
 | 
			
		||||
            write!(
 | 
			
		||||
                f,
 | 
			
		||||
                "{{\n  id: {}\n  filter: {:?}\n}}",
 | 
			
		||||
                self.node_id.encode(),
 | 
			
		||||
                self.filter
 | 
			
		||||
            )
 | 
			
		||||
        } else {
 | 
			
		||||
            write!(f, "{}", self.node_id.encode())
 | 
			
		||||
        }
 | 
			
		||||
        f.debug_struct("NodeRef")
 | 
			
		||||
            .field("node_id", &self.node_id)
 | 
			
		||||
            .field("filter", &self.filter)
 | 
			
		||||
            .finish()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Drop for NodeRef {
 | 
			
		||||
    fn drop(&mut self) {
 | 
			
		||||
        #[cfg(feature = "tracking")]
 | 
			
		||||
        self.operate(|e| e.untrack(self.track_id));
 | 
			
		||||
        self.routing_table.drop_node_ref(self.node_id);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user