Skip to content

Commit

Permalink
new guarantee regarding drops before abort; document what happens whe…
Browse files Browse the repository at this point in the history
…n foreign unwind causes process termination
  • Loading branch information
BatmanAoD committed Aug 31, 2024
1 parent 6ffd283 commit 6b624fe
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 9 deletions.
4 changes: 2 additions & 2 deletions src/behavior-considered-undefined.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ Please read the [Rustonomicon] before writing unsafe code.
* Violating assumptions of the Rust runtime. This is only possible using
mechanisms outside Rust. Most assumptions of the Rust runtime are currently
not explicitly documented.
* For assumptions specifically related to unwinding, see [unwinding-ub].
* For assumptions specifically related to unwinding, see [unwinding-ffi].
* The runtime assumes that a Rust stack frame is not deallocated without
executing destructors for local variables owned by the stack frame. This assumption
can be violated by C functions like `longjmp`.
Expand Down Expand Up @@ -196,5 +196,5 @@ reading uninitialized memory is permitted are inside `union`s and in "padding"
[project-field]: expressions/field-expr.md
[project-tuple]: expressions/tuple-expr.md#tuple-indexing-expressions
[project-slice]: expressions/array-expr.md#array-and-slice-indexing-expressions
[unwinding-ub]: panic.md#unwinding-ub
[unwinding-ffi]: panic.md#unwinding-ffi
[const-promoted]: destructors.md#constant-promotion
12 changes: 12 additions & 0 deletions src/crates-and-source-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,17 @@ use foo::bar as main;
<!-- If the previous section needs updating (from "must take no arguments"
onwards, also update it in the testing.md file -->

### Uncaught foreign unwinding

When a "foreign" unwind (e.g. an exception thrown from C++ code, or a `panic!`
in Rust code compiled or linked with a different runtime) is not caught before
reaching the `main` function, the process will be safely terminated. This may
take the form of an abort, in which case it is not guaranteed that any `Drop`
calls will be executed, and the error output may be less informative than if the
runtime had been terminated by a "native" Rust `panic`.

For more information, see the [panic documentation][panic-docs].

### The `no_main` attribute

The *`no_main` [attribute]* may be applied at the crate level to disable
Expand Down Expand Up @@ -142,6 +153,7 @@ or `_` (U+005F) characters.
[function]: items/functions.md
[module]: items/modules.md
[module path]: paths.md
[panic-docs]: panic.md#unwinding-ffi
[shebang]: input-format.md#shebang-removal
[trait or lifetime bounds]: trait-bounds.md
[where clauses]: items/generics.md#where-clauses
Expand Down
10 changes: 9 additions & 1 deletion src/items/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,12 +244,20 @@ from the "Native unwind" column in the table.
| panic runtime | ABI | `panic`-unwind | Native unwind (unforced) |
| -------------- | ------------ | ------------------------------------- | ----------------------- |
| `panic=unwind` | unwinding | unwind | unwind |
| `panic=unwind` | non-unwinding | abort | [undefined behavior] |
| `panic=unwind` | non-unwinding | abort[^1] | [undefined behavior] |
| `panic=abort` | unwinding | `panic!` aborts (no unwinding occurs) | abort |
| `panic=abort` | non-unwinding | `panic!` aborts (no unwinding occurs) | [undefined behavior] |

[^1]: In this case, either no destructors (`Drop` calls) will run, or all
destructors up until the `extern "C"` boundary (or other such "no unwind"
boundary) will run.

For other considerations and limitations regarding unwinding across FFI
boundaries, see the [relevant section in the Panic documentation][panic-ffi].

[forced-unwinding]: https://rust-lang.github.io/rfcs/2945-c-unwind-abi.html#forced-unwinding
[panic-modes]: ../panic.md#panic-runtimes
[panic-ffi]: ../panic.md#unwind-ffi
[undefined behavior]: ../behavior-considered-undefined.md

## Const functions
Expand Down
13 changes: 7 additions & 6 deletions src/panic.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,14 @@ just as if they had gone out of scope normally.
> continue running).
### Unwinding across FFI boundaries
[unwinding-ub]: #unwinding-across-ffi-boundaries
[unwinding-ffi]: #unwinding-across-ffi-boundaries

It is possible to unwind across FFI boundaries; this creates unique
opportunities for undefined behavior, especially when multiple language
runtimes are involved.
It is possible to unwind across FFI boundaries using an [appropriate ABI
declaration][unwind-abi]. While useful in certain cases, this creates unique
opportunities for undefined behavior, especially when multiple language runtimes
are involved.

Unwinding with the wrong [ABI][abi] is undefined behavior:
Unwinding with the wrong ABI is undefined behavior:

* 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"`,
Expand Down Expand Up @@ -92,10 +93,10 @@ impossible, which can result in both code-size and runtime speed improvements.

See also the [`panic_handler` attribute](runtime.md#the-panic_handler-attribute) which can be used to change the behavior of panics.

[abi]: abi.md
[array indexing]: expressions/array-expr.md#array-and-slice-indexing-expressions
[destructors]: destructors.md
[fn-catch-unwind]: ../std/panic/fn.catch_unwind.html
[macro-panic]: ../std/macro.panic.html
[runtime]: runtime.md
[thread-spawn]: ../std/thread/fn.spawn.html
[unwind-abi]: items/functions.md#unwinding

0 comments on commit 6b624fe

Please sign in to comment.