1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
//! An implementation of the `abort` function that works without the standard library.
//!
//! Provides an [`AbortGuard`] type to abort the process unless explicitly "defused".
//! This can prevent panics from unwinding in the middle of `unsafe` code,
//! which trivially makes the code [exception safe][nomicon-exception-safety].
//!
//! # Available implementations
//! The library offers multiple possible implementations,
//! which can be controlled by using feature flags.
//!
//! 1. Using the Rust standard library [`std::process::abort`] function.
//! This is enabled by using the "std" feature (disabled by default).
//! 2. Using the C standard library [`abort`][libc-abort] function from the [`libc` crate][libc-crate].
//! This requires linking against the C standard library, but not the Rust one.
//! This is enabled by using the "libc" feature (disabled by default).
//! 3. If the `panic!` implementation is known to abort instead of unwinding,
//! then the `abort` function simply triggers a panic.
//! This requires a recent version of Rust (1.60) in order to detect whether panics unwind or abort.
//! 3. If no other implementations are available,
//! then the `abort` function triggers a double-panic.
//! This always triggers an abort regardless of the rust version or compiler settings.
//!
//! [libc-abort]: https://en.cppreference.com/w/c/program/abort
//! [libc-crate]: https://crates.io/crates/libc
//! [nomicon-exception-safety]: https://doc.rust-lang.org/nomicon/exception-safety.html
// doc_cfg only supported on nightly
// very stable in practice...
// currently unstable
/// Abort the process, as if calling [`std::process::abort`]
/// or the C standard library [`abort`](https://en.cppreference.com/w/c/program/abort) function.
///
/// This immediately terminates the process,
/// without calling any destructors or exit codes.
///
///
/// ## Implementations
/// The preferred implementations delegate to a platform-specific abort function.
/// This is enabled whenever `feature = "std"` or `feature = "libc"` is enabled.
/// Using a preferred implementation is equivalent to calling [`immediate_abort`].
///
/// When a platform-specific abort function is not available,
/// this will fall back to using a `panic!` as described in the below section.
///
/// ## Safety
/// This function is **guaranteed** to terminate the process.
/// Unlike the `panic!` function,
/// this function will never unwind into caller code.
///
/// After aborting, this process will never execute any further user code.
/// It is possible some `panic!` code will run inside this function.
/// See the section below for more details.
///
/// ### Invoking `panic!` as fallback
/// No user code will run after invoking this function.
/// However, one of the fallback implementations uses [`core::panic!`] internally.
/// This will trigger the panic hook and run code from the standard library.
/// Outside a call to an `abort` function,
/// this is guaranteed to be the only other code invoked.
/// It will always be passed a `&'static str` argument,
/// which reduces or eliminates use of `core::fmt` machinery.
///
/// For safe code this shouldn't be much of an issue
/// unless you are bothered by the panic hook printing to standard error.
/// To avoid printing to standard output,
/// the easiest workaround is to enable an alternate implementation (see below).
///
/// For unsafe code, there may be further problems.
/// If `unsafe` invariants have been violated,
/// it may be unsafe to execute any code whatever
/// and the abort must be immediate.
///
/// If this usage is unacceptable, invoke the [`immediate_abort`] function instead.
/// This function will never use the fallback implementation.
/// If the primary implementation is missing,
/// it will simply be missing from the library (removed with `cfg`).
/// Alternatively, using the stdlib "panic_immediate_abort" feature should have a similar effect
/// and using the fallback implementation will be fine.
/// As a third choice, `feature = "always-immediate-abort"` will trigger a global compilation error
/// rather than use the fallback implementation.
// immediately delegates
!
/// Immediately call the platform-specific [`abort`] implementation,
/// without invoking any other code.
///
/// Unlike [`abort`], this will never use a fallback implementation that calls `panic!`.
/// Instead, this function will simply not exist.
///
/// In most cases (especially safe code),
/// using the regular [`abort`] function is fine.
// NOTE: Keep doc(cfg(...)) in sync with the underlying reasons for the abort_impl
// immediately delegates
!
/// The fallback implementation.
///
/// ## Rationale for never inlining
/// The most important reason this function should never be inlined
/// is because calling `panic!` might trigger unwinding.
/// We want to guarantee this never happens.
///
/// The secondary reason is that inlining this code would bloat the caller
/// and aborts should always be on the cold-path.
/// The double-panic implementation is two direct calls instead of one.
/// Even the `panic="abort"` case is not inlined,
/// because calling a single-argument function
/// requires an additional load & register move
/// than calling a zero-argument function.
!
/// Abnormally terminate the program by generating a trap instruction.
///
/// This is semantically equivalent to the [LLVM `llvm.trap` intrinsic][llvm-trap].
///
/// One advantage over calling the [`abort`] function is that
/// the caller code-size is often smaller.
///
/// [llvm-trap]: https://releases.llvm.org/18.1.0/docs/LangRef.html#llvm-trap-intrinsic
!
/// Actually invoke the underlying trap instruction.
///
/// When using the "fallback" trap implementation,
/// this function is missing.
!
/// A RAII guard that [aborts](`abort`) the process unless it is explicitly [defused](`AbortGuard::defuse`).
///
/// This is very useful for guaranteeing a section of code will never panic,
/// trivially ensuring the [exception
/// safety](https://doc.rust-lang.org/nomicon/exception-safety.html) of unsafe code.