Skip to content

Commit 003a8a4

Browse files
ehussBatmanAoD
authored andcommitted
Remove "panic runtime" and emphasize panic_handler more
This is a general rework to avoid using the term "panic runtime" (and "panic mode"), since it is poorly defined, potentially confusing, and potentially exposes some internal terminology and details that we may not want to expose. The general outline here is: - Remove the "panic runtime" section. - Move the `panic_handler` attribute to the Panic chapter. - The `panic_handler` attribute text has some editorial changes, and the rule names have changed. - The "Standard behavior" section for `panic_handler` has been reworked, incorporating some of the content from the old panic runtime section. - Added panic.panic_handler.std.no_std - Reword sentences that refer to "runtime", usually pointing to the "handler" instead. Note that there are a few subtle cases where this is not absolutely true.
1 parent 7049886 commit 003a8a4

File tree

7 files changed

+91
-92
lines changed

7 files changed

+91
-92
lines changed

src/attributes.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ The following is an index of all built-in attributes.
370370
[`no_mangle`]: abi.md#the-no_mangle-attribute
371371
[`no_std`]: names/preludes.md#the-no_std-attribute
372372
[`non_exhaustive`]: attributes/type_system.md#the-non_exhaustive-attribute
373-
[`panic_handler`]: runtime.md#the-panic_handler-attribute
373+
[`panic_handler`]: panic.md#the-panic_handler-attribute
374374
[`path`]: items/modules.md#the-path-attribute
375375
[`proc_macro_attribute`]: procedural-macros.md#attribute-macros
376376
[`proc_macro_derive`]: procedural-macros.md#derive-macros

src/crates-and-source-files.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ r[crate.uncaught-foreign-unwinding]
126126
### Uncaught foreign unwinding
127127

128128
When a "foreign" unwind (e.g. an exception thrown from C++ code, or a `panic!`
129-
in Rust code compiled or linked with a different runtime) propagates beyond
129+
in Rust code using a different panic handler) propagates beyond
130130
the `main` function, the process will be safely terminated. This may
131131
take the form of an abort, in which case it is not guaranteed that any `Drop`
132132
calls will be executed, and the error output may be less informative than if the

src/destructors.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ destructors will not be run.
444444

445445
The standard library provides [`std::process::exit`] and
446446
[`std::process::abort`] to do this explicitly. Additionally, if the
447-
[panic-mode] is set to `abort`, panicking will always terminate the process
447+
[panic handler][panic.panic_handler.std] is set to `abort`, panicking will always terminate the process
448448
without destructors being run.
449449

450450
There is one additional case to be aware of: when a panic reaches a
@@ -462,7 +462,6 @@ destructors up until the ABI boundary will run.
462462
[lazy boolean expression]: expressions/operator-expr.md#lazy-boolean-operators
463463
[non-unwinding ABI boundary]: items/functions.md#unwinding
464464
[panic]: panic.md
465-
[panic-mode]: panic.md#panic-runtimes
466465
[place context]: expressions.md#place-expressions-and-value-expressions
467466
[promoted]: destructors.md#constant-promotion
468467
[scrutinee]: glossary.md#scrutinee

src/items/functions.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ r[items.fn.extern.unwind]
259259
r[items.fn.extern.unwind.intro]
260260
Most ABI strings come in two variants, one with an `-unwind` suffix and one without.
261261
The `Rust` ABI always permits unwinding, so there is no `Rust-unwind` ABI. The
262-
choice of ABI, together with the runtime [panic mode][panic-modes], determines
262+
choice of ABI, together with the runtime [panic handler], determines
263263
the behavior when unwinding out of a function.
264264

265265
r[items.fn.extern.unwind.behavior]
@@ -301,7 +301,7 @@ For other considerations and limitations regarding unwinding across FFI
301301
boundaries, see the [relevant section in the Panic documentation][panic-ffi].
302302

303303
[forced-unwinding]: https://rust-lang.github.io/rfcs/2945-c-unwind-abi.html#forced-unwinding
304-
[panic-modes]: ../panic.md#panic-runtimes
304+
[panic handler]: ../panic.md#the-panic_handler-attribute
305305
[panic-ffi]: ../panic.md#unwinding-across-ffi-boundaries
306306
[panicking]: ../panic.md
307307
[undefined behavior]: ../behavior-considered-undefined.md

src/linkage.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ Panic unwinding can only be used if the binary is built consistently according t
283283

284284
r[link.unwinding.potential]
285285
A Rust artifact is called *potentially unwinding* if any of the following conditions is met:
286-
- The artifact is linked with [the `unwind` panic runtime][panic-runtime].
286+
- The artifact uses the [`unwind` panic handler][panic.panic_handler].
287287
- The artifact contains a crate built with the `unwind` [panic strategy] that makes a call
288288
to a function using a `-unwind` ABI.
289289
- The artifact makes a `"Rust"` ABI call to code running in another Rust
@@ -313,7 +313,6 @@ Otherwise, unwinding can cause undefined behavior.
313313
[`cfg` attribute `target_feature` option]: conditional-compilation.md#target_feature
314314
[`ffi_unwind_calls` lint]: ../rustc/lints/listing/allowed-by-default.html#ffi-unwind-calls
315315
[configuration option]: conditional-compilation.md
316-
[panic-runtime]: panic.md#panic-runtimes
317316
[procedural macros]: procedural-macros.md
318317
[panic strategy]: panic.md#panic-strategy
319318
[`-C panic`]: ../rustc/codegen-options/index.html#panic

src/panic.md

+71-19
Original file line numberDiff line numberDiff line change
@@ -10,56 +10,104 @@ Some language constructs, such as out-of-bounds [array indexing], panic automati
1010
r[panic.control]
1111
There are also language features that provide a level of control over panic behavior:
1212

13-
* A [_panic runtime_](#panic-runtimes) defined how a panic is handled during runtime.
13+
* A [_panic handler_][panic handler] defines the behavior of a panic.
1414
* [FFI ABIs](items/functions.md#unwinding) may alter how panics behave.
1515

1616
> [!NOTE]
1717
> The standard library provides the capability to explicitly panic via the [`panic!` macro][panic!].
1818
19-
r[panic.runtime]
20-
## Panic runtimes
19+
r[panic.panic_handler]
20+
## The `panic_handler` attribute
2121

22-
r[panic.runtime.intro]
23-
The actual behavior and implementation of a panic is controlled by the _panic runtime_. The panic runtime is a handler linked into the output which provides the necessary implementation for panicking.
22+
r[panic.panic_handler.intro]
23+
The *`panic_handler` attribute* can be applied to a function to define the behavior of panics.
2424

25-
r[panic.runtime.kinds]
26-
The following panic runtimes are provided by the standard library:
25+
r[panic.panic_handler.allowed-positions]
26+
The `panic_handler` attribute can only be applied to a function with signature `fn(&PanicInfo) -> !`.
27+
28+
> [!NOTE]
29+
> The [`PanicInfo`] struct contains information about the location of the panic.
30+
31+
r[panic.panic_handler.unique]
32+
There must be a single `panic_handler` function in the dependency graph.
33+
34+
Below is shown a `panic_handler` function that logs the panic message and then halts the thread.
35+
36+
<!-- ignore: test infrastructure can't handle no_std -->
37+
```rust,ignore
38+
#![no_std]
39+
40+
use core::fmt::{self, Write};
41+
use core::panic::PanicInfo;
42+
43+
struct Sink {
44+
// ..
45+
# _0: (),
46+
}
47+
#
48+
# impl Sink {
49+
# fn new() -> Sink { Sink { _0: () }}
50+
# }
51+
#
52+
# impl fmt::Write for Sink {
53+
# fn write_str(&mut self, _: &str) -> fmt::Result { Ok(()) }
54+
# }
55+
56+
#[panic_handler]
57+
fn panic(info: &PanicInfo) -> ! {
58+
let mut sink = Sink::new();
59+
60+
// logs "panicked at '$reason', src/main.rs:27:4" to some `sink`
61+
let _ = writeln!(sink, "{}", info);
62+
63+
loop {}
64+
}
65+
```
66+
67+
r[panic.panic_handler.std]
68+
### Standard behavior
69+
70+
r[panic.panic_handler.std.kinds]
71+
`std` provides two different panic handlers:
2772

2873
* `unwind` --- unwinds the stack and is potentially recoverable.
2974
* `abort` ---- aborts the process and is non-recoverable.
3075

31-
Not all targets may provide the `unwind` runtime.
32-
33-
The default runtime depends on the target platform, but is generally `unwind` on platforms with native support for C++ exceptions.
76+
Not all targets may provide the `unwind` handler.
3477

3578
> [!NOTE]
36-
> The panic runtime can be chosen in `rustc` with the [`-C panic`] CLI flag when building any crate type except an rlib.
79+
> The panic handler used when linking with `std` can be set with the [`-C panic`] CLI flag. The default for most targets is `unwind`.
80+
>
81+
> The standard library's panic behavior can be modified at runtime with the [`std::panic::set_hook`] function.
3782
38-
See also the [`panic_handler` attribute](runtime.md#the-panic_handler-attribute) which can be used to change the behavior of panics.
83+
r[panic.panic_handler.std.no_std]
84+
Linking a [`no_std`] binary, dylib, cdylib, or staticlib will require specifying your own panic handler.
3985

4086
r[panic.strategy]
4187
## Panic strategy
4288

4389
r[panic.strategy.intro]
44-
The _panic strategy_ defines the kind of panic runtime that a crate is built to support.
90+
The _panic strategy_ defines the kind of panic behavior that a crate is built to support.
4591

4692
> [!NOTE]
4793
> The panic strategy can be chosen in `rustc` with the [`-C panic`] CLI flag.
94+
>
95+
> When generating a binary, dylib, cdylib, or staticlib and linking with `std`, the `-C panic` CLI flag also influences which [panic handler] is used.
4896
4997
> [!NOTE]
5098
> When compiling code with the `abort` panic strategy, the optimizer may assume that unwinding across Rust frames is impossible, which can result in both code-size and runtime speed improvements.
5199
52100
> [!NOTE]
53-
> See [link.unwinding] for restrictions on linking crates with different panic strategies. An implication is that crates built with the `unwind` strategy can use the `abort` runtime, but not vice-versa.
101+
> See [link.unwinding] for restrictions on linking crates with different panic strategies. An implication is that crates built with the `unwind` strategy can use the `abort` panic handler, but the `abort` strategy cannot use the `unwind` panic handler.
54102
55103
r[panic.unwind]
56104
## Unwinding
57105

58106
r[panic.unwind.intro]
59-
Panicking may either be recoverable or non-recoverable, though it can be configured (by choosing the `abort` panic runtime) to always be non-recoverable. (The converse is not true: the `unwind` runtime does not guarantee that all panics are recoverable, only that panicking via the `panic!` macro and similar standard library mechanisms is recoverable.)
107+
Panicking may either be recoverable or non-recoverable, though it can be configured (by choosing a non-unwinding panic handler) to always be non-recoverable. (The converse is not true: the `unwind` handler does not guarantee that all panics are recoverable, only that panicking via the `panic!` macro and similar standard library mechanisms is recoverable.)
60108

61109
r[panic.unwind.destruction]
62-
When panic recovery occurs, the `unwind` runtime "unwinds" Rust frames, just as C++'s `throw` unwinds C++ frames, until the panic reaches the point of recovery (for instance at a thread boundary). This means that as the panic traverses Rust frames, live objects in those frames that [implement `Drop`][destructors] will have their `drop` methods called. Thus, when normal execution resumes, no-longer-accessible objects will have been "cleaned up" just as if they had gone out of scope normally.
110+
When a panic occurs, the `unwind` handler "unwinds" Rust frames, just as C++'s `throw` unwinds C++ frames, until the panic reaches the point of recovery (for instance at a thread boundary). This means that as the panic traverses Rust frames, live objects in those frames that [implement `Drop`][destructors] will have their `drop` methods called. Thus, when normal execution resumes, no-longer-accessible objects will have been "cleaned up" just as if they had gone out of scope normally.
63111

64112
> [!NOTE]
65113
> As long as this guarantee of resource-cleanup is preserved, "unwinding" may be implemented without actually using the mechanism used by C++ for the target platform.
@@ -77,7 +125,7 @@ r[panic.unwind.ffi.undefined]
77125
Unwinding with the wrong ABI is undefined behavior:
78126

79127
* Causing an unwind into Rust code from a foreign function that was called via a function declaration or pointer declared with a non-unwinding ABI, such as `"C"`, `"system"`, etc. (For example, this case occurs when such a function written in C++ throws an exception that is uncaught and propagates to Rust.)
80-
* Calling a Rust `extern` function that unwinds (with `extern "C-unwind"` or another ABI that permits unwinding) from a runtime that does not support unwinding, such as code compiled with GCC or Clang using `-fno-exceptions`
128+
* Calling a Rust `extern` function that unwinds (with `extern "C-unwind"` or another ABI that permits unwinding) from code that does not support unwinding, such as code compiled with GCC or Clang using `-fno-exceptions`
81129

82130
r[panic.unwind.ffi.catch-foreign]
83131
Catching a foreign unwinding operation (such as a C++ exception) using [`std::panic::catch_unwind`], [`std::thread::JoinHandle::join`], or by letting it propagate beyond the Rust `main()` function or thread root will have one of two behaviors, and it is unspecified which will occur:
@@ -86,13 +134,17 @@ Catching a foreign unwinding operation (such as a C++ exception) using [`std::pa
86134
* The function returns a [`Result::Err`] containing an opaque type.
87135

88136
> [!NOTE]
89-
> Rust code compiled or linked with a different instance of the Rust runtime counts as a "foreign exception" for the purpose of this guarantee. Thus, a library that uses `panic!` and is linked against one version of the Rust standard library, invoked from an application that uses a different version of the standard library, may cause the entire application to crash even if the library is only used within a child thread.
137+
> Rust code compiled or linked with a different instance of the Rust standard library counts as a "foreign exception" for the purpose of this guarantee. Thus, a library that uses `panic!` and is linked against one version of the Rust standard library, invoked from an application that uses a different version of the standard library, may cause the entire application to abort even if the library is only used within a child thread.
90138
91139
r[panic.unwind.ffi.dispose-panic]
92140
There are currently no guarantees about the behavior that occurs when a foreign runtime attempts to dispose of, or rethrow, a Rust `panic` payload. In other words, an unwind originated from a Rust runtime must either lead to termination of the process or be caught by the same runtime.
93141

142+
[`-C panic`]: ../rustc/codegen-options/index.html#panic
143+
[`no_std`]: names/preludes.md#the-no_std-attribute
144+
[`PanicInfo`]: core::panic::PanicInfo
94145
[array indexing]: expressions/array-expr.md#array-and-slice-indexing-expressions
146+
[attribute]: attributes.md
95147
[destructors]: destructors.md
148+
[panic handler]: #the-panic_handler-attribute
96149
[runtime]: runtime.md
97150
[unwind-abi]: items/functions.md#unwinding
98-
[`-C panic`]: ../rustc/codegen-options/index.html#panic

src/runtime.md

+14-65
Original file line numberDiff line numberDiff line change
@@ -3,66 +3,6 @@ r[runtime]
33

44
This section documents features that define some aspects of the Rust runtime.
55

6-
r[runtime.panic_handler]
7-
## The `panic_handler` attribute
8-
9-
r[runtime.panic_handler.allowed-positions]
10-
The *`panic_handler` attribute* can only be applied to a function with signature
11-
`fn(&PanicInfo) -> !`.
12-
13-
r[runtime.panic_handler.intro]
14-
The function marked with this [attribute] defines the behavior of panics.
15-
16-
r[runtime.panic_handler.panic-info]
17-
The [`PanicInfo`] struct contains information about the location of the panic.
18-
19-
r[runtime.panic_handler.unique]
20-
There must be a single `panic_handler` function in the dependency graph of a binary, dylib or cdylib crate.
21-
22-
Below is shown a `panic_handler` function that logs the panic message and then halts the
23-
thread.
24-
25-
<!-- ignore: test infrastructure can't handle no_std -->
26-
```rust,ignore
27-
#![no_std]
28-
29-
use core::fmt::{self, Write};
30-
use core::panic::PanicInfo;
31-
32-
struct Sink {
33-
// ..
34-
# _0: (),
35-
}
36-
#
37-
# impl Sink {
38-
# fn new() -> Sink { Sink { _0: () }}
39-
# }
40-
#
41-
# impl fmt::Write for Sink {
42-
# fn write_str(&mut self, _: &str) -> fmt::Result { Ok(()) }
43-
# }
44-
45-
#[panic_handler]
46-
fn panic(info: &PanicInfo) -> ! {
47-
let mut sink = Sink::new();
48-
49-
// logs "panicked at '$reason', src/main.rs:27:4" to some `sink`
50-
let _ = writeln!(sink, "{}", info);
51-
52-
loop {}
53-
}
54-
```
55-
56-
r[runtime.panic_handler.std]
57-
### Standard behavior
58-
59-
The standard library provides an implementation of `panic_handler` that
60-
defaults to unwinding the stack but that can be [changed to abort the
61-
process][abort]. See [panic runtimes] for more details.
62-
63-
The standard library's panic behavior can be modified at runtime with the
64-
[`set_hook` function][set_hook].
65-
666
r[runtime.global_allocator]
677
## The `global_allocator` attribute
688

@@ -98,11 +38,20 @@ display a console window on startup. It will run detached from any existing cons
9838

9939
[_MetaNameValueStr_]: attributes.md#meta-item-attribute-syntax
10040
[`GlobalAlloc`]: alloc::alloc::GlobalAlloc
101-
[`PanicInfo`]: core::panic::PanicInfo
102-
[abort]: ../book/ch09-01-unrecoverable-errors-with-panic.html
103-
[attribute]: attributes.md
10441
[crate types]: linkage.md
105-
[panic runtimes]: panic.md#panic-runtimes
106-
[set_hook]: std::panic::set_hook
10742
[static item]: items/static-items.md
10843
[subsystem]: https://msdn.microsoft.com/en-us/library/fcc1zstk.aspx
44+
45+
<script>
46+
(function() {
47+
var fragments = {
48+
"#the-panic_handler-attribute": "panic.html#the-panic_handler-attribute",
49+
};
50+
var target = fragments[window.location.hash];
51+
if (target) {
52+
var url = window.location.toString();
53+
var base = url.substring(0, url.lastIndexOf('/'));
54+
window.location.replace(base + "/" + target);
55+
}
56+
})();
57+
</script>

0 commit comments

Comments
 (0)