Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit 6fe8cd4

Browse files
Runtime diagnostics for leaked messages in unbounded channels (part 2) (#13020)
* Fix code review issues * Clarify doc * Get rid of backtrace mutex * kick CI
1 parent 27e9a1c commit 6fe8cd4

File tree

5 files changed

+69
-48
lines changed

5 files changed

+69
-48
lines changed

Cargo.lock

Lines changed: 45 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/network/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"]
1717
array-bytes = "4.1"
1818
async-trait = "0.1"
1919
asynchronous-codec = "0.6"
20+
backtrace = "0.3.67"
2021
bytes = "1"
2122
codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] }
2223
either = "1.5.3"

client/network/src/service/out_events.rs

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@
3131
//! - Send events by calling [`OutChannels::send`]. Events are cloned for each sender in the
3232
//! collection.
3333
34+
use backtrace::Backtrace;
3435
use futures::{channel::mpsc, prelude::*, ready, stream::FusedStream};
3536
use log::error;
3637
use parking_lot::Mutex;
3738
use prometheus_endpoint::{register, CounterVec, GaugeVec, Opts, PrometheusError, Registry, U64};
3839
use sc_network_common::protocol::event::Event;
3940
use std::{
40-
backtrace::{Backtrace, BacktraceStatus},
4141
cell::RefCell,
4242
fmt,
4343
pin::Pin,
@@ -62,7 +62,7 @@ pub fn channel(name: &'static str, queue_size_warning: i64) -> (Sender, Receiver
6262
queue_size: queue_size.clone(),
6363
queue_size_warning,
6464
warning_fired: false,
65-
creation_backtrace: Backtrace::capture(),
65+
creation_backtrace: Backtrace::new_unresolved(),
6666
metrics: metrics.clone(),
6767
};
6868
let rx = Receiver { inner: rx, name, queue_size, metrics };
@@ -91,7 +91,8 @@ pub struct Sender {
9191
warning_fired: bool,
9292
/// Backtrace of a place where the channel was created.
9393
creation_backtrace: Backtrace,
94-
/// Clone of [`Receiver::metrics`].
94+
/// Clone of [`Receiver::metrics`]. Will be initialized when [`Sender`] is added to
95+
/// [`OutChannels`] with `OutChannels::push()`.
9596
metrics: Arc<Mutex<Option<Arc<Option<Metrics>>>>>,
9697
}
9798

@@ -193,17 +194,12 @@ impl OutChannels {
193194
let queue_size = sender.queue_size.fetch_add(1, Ordering::Relaxed);
194195
if queue_size == sender.queue_size_warning && !sender.warning_fired {
195196
sender.warning_fired = true;
196-
match sender.creation_backtrace.status() {
197-
BacktraceStatus::Captured => error!(
198-
"The number of unprocessed events in channel `{}` reached {}.\n\
199-
The channel was created at:\n{}",
200-
sender.name, sender.queue_size_warning, sender.creation_backtrace,
201-
),
202-
_ => error!(
203-
"The number of unprocessed events in channel `{}` reached {}.",
204-
sender.name, sender.queue_size_warning,
205-
),
206-
}
197+
sender.creation_backtrace.resolve();
198+
error!(
199+
"The number of unprocessed events in channel `{}` reached {}.\n\
200+
The channel was created at:\n{:?}",
201+
sender.name, sender.queue_size_warning, sender.creation_backtrace,
202+
);
207203
}
208204
sender.inner.unbounded_send(event.clone()).is_ok()
209205
});

client/utils/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ description = "I/O for Substrate runtimes"
1010
readme = "README.md"
1111

1212
[dependencies]
13+
backtrace = "0.3.67"
1314
futures = "0.3.21"
1415
futures-timer = "3.0.2"
1516
lazy_static = "1.4.0"

client/utils/src/mpsc.rs

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ mod inner {
3737
mod inner {
3838
// tracing implementation
3939
use crate::metrics::UNBOUNDED_CHANNELS_COUNTER;
40+
use backtrace::Backtrace;
4041
use futures::{
4142
channel::mpsc::{
4243
self, SendError, TryRecvError, TrySendError, UnboundedReceiver, UnboundedSender,
@@ -47,7 +48,6 @@ mod inner {
4748
};
4849
use log::error;
4950
use std::{
50-
backtrace::{Backtrace, BacktraceStatus},
5151
pin::Pin,
5252
sync::{
5353
atomic::{AtomicBool, AtomicI64, Ordering},
@@ -108,7 +108,7 @@ mod inner {
108108
queue_size: queue_size.clone(),
109109
queue_size_warning,
110110
warning_fired: Arc::new(AtomicBool::new(false)),
111-
creation_backtrace: Arc::new(Backtrace::capture()),
111+
creation_backtrace: Arc::new(Backtrace::new_unresolved()),
112112
};
113113
let receiver = TracingUnboundedReceiver { inner: r, name, queue_size };
114114
(sender, receiver)
@@ -149,23 +149,20 @@ mod inner {
149149

150150
let queue_size = self.queue_size.fetch_add(1, Ordering::Relaxed);
151151
if queue_size == self.queue_size_warning &&
152-
!self.warning_fired.load(Ordering::Relaxed)
152+
self.warning_fired
153+
.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
154+
.is_ok()
153155
{
154156
// `warning_fired` and `queue_size` are not synchronized, so it's possible
155157
// that the warning is fired few times before the `warning_fired` is seen
156158
// by all threads. This seems better than introducing a mutex guarding them.
157-
self.warning_fired.store(true, Ordering::Relaxed);
158-
match self.creation_backtrace.status() {
159-
BacktraceStatus::Captured => error!(
160-
"The number of unprocessed messages in channel `{}` reached {}.\n\
161-
The channel was created at:\n{}",
162-
self.name, self.queue_size_warning, self.creation_backtrace,
163-
),
164-
_ => error!(
165-
"The number of unprocessed messages in channel `{}` reached {}.",
166-
self.name, self.queue_size_warning,
167-
),
168-
}
159+
let mut backtrace = (*self.creation_backtrace).clone();
160+
backtrace.resolve();
161+
error!(
162+
"The number of unprocessed messages in channel `{}` reached {}.\n\
163+
The channel was created at:\n{:?}",
164+
self.name, self.queue_size_warning, backtrace,
165+
);
169166
}
170167

171168
s

0 commit comments

Comments
 (0)