4
4
5
5
use crate :: any:: Any ;
6
6
use crate :: collections;
7
+ use crate :: mem;
7
8
use crate :: panicking;
8
9
use crate :: sync:: { Mutex , RwLock } ;
9
10
use crate :: thread:: Result ;
@@ -106,6 +107,11 @@ where
106
107
/// aborting the process as well. This function *only* catches unwinding panics,
107
108
/// not those that abort the process.
108
109
///
110
+ /// This function returns the payload that the closure panicked with. Because the payload
111
+ /// is allowed to be any type, it is possible for it to be a type that itself panics when
112
+ /// dropped. To make sure that badly-behaved panic payloads like these do not cause bugs,
113
+ /// use [`drop_unwind`] instead.
114
+ ///
109
115
/// Also note that unwinding into Rust code with a foreign exception (e.g.
110
116
/// an exception thrown from C++ code) is undefined behavior.
111
117
///
@@ -129,6 +135,66 @@ pub fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> {
129
135
unsafe { panicking:: r#try ( f) }
130
136
}
131
137
138
+ /// Invokes a closure, dropping the cause of an unwinding panic if one occurs.
139
+ ///
140
+ /// Unlike [`catch_unwind`], this function does not return the payload that the
141
+ /// closure panicked with if it panics. Instead, the payload is dropped in such
142
+ /// a way that avoids propagating panics the payload causes when it is dropped.
143
+ /// As such, unlike [`catch_unwind`], you can safely ignore and drop the result
144
+ /// of this function without potentially causing the outer function to unwind.
145
+ ///
146
+ /// It is currently undefined behavior to unwind from Rust code into foreign
147
+ /// code, so this function is particularly useful when Rust is called from
148
+ /// another language (normally C). This can run arbitrary Rust code, capturing a
149
+ /// panic and allowing a graceful handling of the error.
150
+ ///
151
+ /// The closure provided is required to adhere to the [`UnwindSafe`] trait to ensure
152
+ /// that all captured variables are safe to cross this boundary. The purpose of
153
+ /// this bound is to encode the concept of [exception safety][rfc] in the type
154
+ /// system. Most usage of this function should not need to worry about this
155
+ /// bound as programs are naturally unwind safe without `unsafe` code. If it
156
+ /// becomes a problem the [`AssertUnwindSafe`] wrapper struct can be used to quickly
157
+ /// assert that the usage here is indeed unwind safe.
158
+ ///
159
+ /// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md
160
+ ///
161
+ /// # Notes
162
+ ///
163
+ /// Note that this function **may not catch all panics** in Rust. A panic in
164
+ /// Rust is not always implemented via unwinding, but can be implemented by
165
+ /// aborting the process as well. This function *only* catches unwinding panics,
166
+ /// not those that abort the process.
167
+ ///
168
+ /// Also note that unwinding into Rust code with a foreign exception (e.g.
169
+ /// an exception thrown from C++ code) is undefined behavior.
170
+ ///
171
+ /// # Examples
172
+ ///
173
+ /// ```
174
+ /// #![feature(drop_unwind)]
175
+ ///
176
+ /// use std::panic;
177
+ ///
178
+ /// let _ = panic::drop_unwind(|| {
179
+ /// panic!("oh no!");
180
+ /// });
181
+ /// println!("hello!");
182
+ /// ```
183
+ #[ unstable( feature = "drop_unwind" , issue = "none" ) ]
184
+ pub fn drop_unwind < F : FnOnce ( ) -> R + UnwindSafe , R > ( f : F ) -> core:: result:: Result < R , ( ) > {
185
+ struct AbortOnDrop ;
186
+ impl Drop for AbortOnDrop {
187
+ fn drop ( & mut self ) {
188
+ crate :: process:: abort ( ) ;
189
+ }
190
+ }
191
+
192
+ let abort_on_drop = AbortOnDrop ;
193
+ let res = catch_unwind ( f) . map_err ( drop) ;
194
+ mem:: forget ( abort_on_drop) ;
195
+ res
196
+ }
197
+
132
198
/// Triggers a panic without invoking the panic hook.
133
199
///
134
200
/// This is designed to be used in conjunction with [`catch_unwind`] to, for
0 commit comments