| 1 | use std::{sync::mpsc, thread, time::Duration}; |
| 2 | use tracing::{ |
| 3 | metadata::Metadata, |
| 4 | span, |
| 5 | subscriber::{self, Interest, Subscriber}, |
| 6 | Event, |
| 7 | }; |
| 8 | |
| 9 | #[test] |
| 10 | fn register_callsite_doesnt_deadlock() { |
| 11 | pub struct EvilSubscriber; |
| 12 | |
| 13 | impl Subscriber for EvilSubscriber { |
| 14 | fn register_callsite(&self, meta: &'static Metadata<'static>) -> Interest { |
| 15 | tracing::info!(?meta, "registered a callsite" ); |
| 16 | Interest::always() |
| 17 | } |
| 18 | |
| 19 | fn enabled(&self, _: &Metadata<'_>) -> bool { |
| 20 | true |
| 21 | } |
| 22 | fn new_span(&self, _: &span::Attributes<'_>) -> span::Id { |
| 23 | span::Id::from_u64(1) |
| 24 | } |
| 25 | fn record(&self, _: &span::Id, _: &span::Record<'_>) {} |
| 26 | fn record_follows_from(&self, _: &span::Id, _: &span::Id) {} |
| 27 | fn event(&self, _: &Event<'_>) {} |
| 28 | fn enter(&self, _: &span::Id) {} |
| 29 | fn exit(&self, _: &span::Id) {} |
| 30 | } |
| 31 | |
| 32 | subscriber::set_global_default(EvilSubscriber).unwrap(); |
| 33 | |
| 34 | // spawn a thread, and assert it doesn't hang... |
| 35 | let (tx, didnt_hang) = mpsc::channel(); |
| 36 | let th = thread::spawn(move || { |
| 37 | tracing::info!("hello world!" ); |
| 38 | tx.send(()).unwrap(); |
| 39 | }); |
| 40 | |
| 41 | didnt_hang |
| 42 | // Note: 60 seconds is *way* more than enough, but let's be generous in |
| 43 | // case of e.g. slow CI machines. |
| 44 | .recv_timeout(Duration::from_secs(60)) |
| 45 | .expect("the thread must not have hung!" ); |
| 46 | th.join().expect("thread should join successfully" ); |
| 47 | } |
| 48 | |