You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
Copy file name to clipboardExpand all lines: src/panic.md
+71-19
Original file line number
Diff line number
Diff line change
@@ -10,56 +10,104 @@ Some language constructs, such as out-of-bounds [array indexing], panic automati
10
10
r[panic.control]
11
11
There are also language features that provide a level of control over panic behavior:
12
12
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.
14
14
*[FFI ABIs](items/functions.md#unwinding) may alter how panics behave.
15
15
16
16
> [!NOTE]
17
17
> The standard library provides the capability to explicitly panic via the [`panic!` macro][panic!].
18
18
19
-
r[panic.runtime]
20
-
## Panic runtimes
19
+
r[panic.panic_handler]
20
+
## The `panic_handler` attribute
21
21
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.
24
24
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 -->
// 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:
27
72
28
73
*`unwind` --- unwinds the stack and is potentially recoverable.
29
74
*`abort` ---- aborts the process and is non-recoverable.
30
75
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.
34
77
35
78
> [!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.
37
82
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.
39
85
40
86
r[panic.strategy]
41
87
## Panic strategy
42
88
43
89
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.
45
91
46
92
> [!NOTE]
47
93
> 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.
48
96
49
97
> [!NOTE]
50
98
> 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.
51
99
52
100
> [!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.
54
102
55
103
r[panic.unwind]
56
104
## Unwinding
57
105
58
106
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.)
60
108
61
109
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.
63
111
64
112
> [!NOTE]
65
113
> 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]
77
125
Unwinding with the wrong ABI is undefined behavior:
78
126
79
127
* 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`
81
129
82
130
r[panic.unwind.ffi.catch-foreign]
83
131
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
86
134
* The function returns a [`Result::Err`] containing an opaque type.
87
135
88
136
> [!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.
90
138
91
139
r[panic.unwind.ffi.dispose-panic]
92
140
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.
0 commit comments