zebra_chain/diagnostic/task.rs
1//! Diagnostic types and functions for Zebra tasks:
2//! - OS thread handling
3//! - async future task handling
4//! - errors and panics
5
6#[cfg(feature = "async-error")]
7pub mod future;
8
9pub mod thread;
10
11/// A trait that checks a task's return value for panics.
12pub trait CheckForPanics: Sized {
13 /// The output type, after removing panics from `Self`.
14 type Output;
15
16 /// Check if `self` contains a panic payload or an unexpected termination, then panic.
17 /// Otherwise, return the non-panic part of `self`.
18 ///
19 /// # Panics
20 ///
21 /// If `self` contains a panic payload or an unexpected termination.
22 #[track_caller]
23 fn panic_if_task_has_finished(self) -> Self::Output {
24 self.check_for_panics_with(true)
25 }
26
27 /// Check if `self` contains a panic payload, then panic.
28 /// Otherwise, return the non-panic part of `self`.
29 ///
30 /// # Panics
31 ///
32 /// If `self` contains a panic payload.
33 #[track_caller]
34 fn panic_if_task_has_panicked(self) -> Self::Output {
35 self.check_for_panics_with(false)
36 }
37
38 /// Check if `self` contains a panic payload, then panic. Also panics if
39 /// `panic_on_unexpected_termination` is true, and `self` is an unexpected termination.
40 /// Otherwise, return the non-panic part of `self`.
41 ///
42 /// # Panics
43 ///
44 /// If `self` contains a panic payload, or if we're panicking on unexpected terminations.
45 #[track_caller]
46 fn check_for_panics_with(self, panic_on_unexpected_termination: bool) -> Self::Output;
47}
48
49/// A trait that waits for a task to finish, then handles panics and cancellations.
50pub trait WaitForPanics: Sized {
51 /// The underlying task output, after removing panics and unwrapping termination results.
52 type Output;
53
54 /// Waits for `self` to finish, then check if its output is:
55 /// - a panic payload: resume that panic,
56 /// - an unexpected termination: panic with that error,
57 /// - an expected termination: hang waiting for shutdown.
58 ///
59 /// Otherwise, returns the task return value of `self`.
60 ///
61 /// # Panics
62 ///
63 /// If `self` contains a panic payload or an unexpected termination.
64 ///
65 /// # Hangs
66 ///
67 /// If `self` contains an expected termination, and we're shutting down anyway.
68 #[track_caller]
69 fn wait_and_panic_on_unexpected_termination(self) -> Self::Output {
70 self.wait_for_panics_with(true)
71 }
72
73 /// Waits for `self` to finish, then check if its output is:
74 /// - a panic payload: resume that panic,
75 /// - a task termination: hang waiting for shutdown.
76 ///
77 /// Otherwise, returns the task return value of `self`.
78 ///
79 /// # Panics
80 ///
81 /// If `self` contains a panic payload.
82 ///
83 /// # Hangs
84 ///
85 /// If `self` contains a task termination.
86 #[track_caller]
87 fn wait_for_panics(self) -> Self::Output {
88 self.wait_for_panics_with(false)
89 }
90
91 /// Waits for `self` to finish, then check if its output is:
92 /// - a panic payload: resume that panic,
93 /// - an unexpected termination:
94 /// - if `panic_on_unexpected_termination` is true, panic with that error,
95 /// - otherwise, hang waiting for shutdown,
96 /// - an expected termination: hang waiting for shutdown.
97 ///
98 /// Otherwise, returns the task return value of `self`.
99 ///
100 /// # Panics
101 ///
102 /// If `self` contains a panic payload, or if we're panicking on unexpected terminations.
103 ///
104 /// # Hangs
105 ///
106 /// If `self` contains an expected or ignored termination, and we're shutting down anyway.
107 #[track_caller]
108 fn wait_for_panics_with(self, panic_on_unexpected_termination: bool) -> Self::Output;
109}