|
| 1 | +- Feature Name: exit |
| 2 | +- Start Date: 2015-03-24 |
| 3 | +- RFC PR: https://github.com/rust-lang/rfcs/pull/1011 |
| 4 | +- Rust Issue: (leave this empty) |
| 5 | + |
| 6 | +# Summary |
| 7 | + |
| 8 | +Add a function to the `std::process` module to exit the process immediately with |
| 9 | +a specified exit code. |
| 10 | + |
| 11 | +# Motivation |
| 12 | + |
| 13 | +Currently there is no stable method to exit a program in Rust with a nonzero |
| 14 | +exit code without panicking. The current unstable method for doing so is by |
| 15 | +using the `exit_status` feature with the `std::env::set_exit_status` function. |
| 16 | + |
| 17 | +This function has not been stabilized as it diverges from the system APIs (there |
| 18 | +is no equivalent) and it represents an odd piece of global state for a Rust |
| 19 | +program to have. One example of odd behavior that may arise is that if a library |
| 20 | +calls `env::set_exit_status`, then the process is not guaranteed to exit with |
| 21 | +that status (e.g. Rust was called from C). |
| 22 | + |
| 23 | +The purpose of this RFC is to provide at least one method on the path to |
| 24 | +stabilization which will provide a method to exit a process with an arbitrary |
| 25 | +exit code. |
| 26 | + |
| 27 | +# Detailed design |
| 28 | + |
| 29 | +The following function will be added to the `std::process` module: |
| 30 | + |
| 31 | +```rust |
| 32 | +/// Terminates the current process with the specified exit code. |
| 33 | +/// |
| 34 | +/// This function will never return and will immediately terminate the current |
| 35 | +/// process. The exit code is passed through to the underlying OS and will be |
| 36 | +/// available for consumption by another process. |
| 37 | +/// |
| 38 | +/// Note that because this function never returns, and that it terminates the |
| 39 | +/// process, no destructors on the current stack or any other thread's stack |
| 40 | +/// will be run. If a clean shutdown is needed it is recommended to only call |
| 41 | +/// this function at a known point where there are no more destructors left |
| 42 | +/// to run. |
| 43 | +pub fn exit(code: i32) -> !; |
| 44 | +``` |
| 45 | + |
| 46 | +Implementation-wise this will correspond to the [`exit` function][unix] on unix |
| 47 | +and the [`ExitProcess` function][win] on windows. |
| 48 | + |
| 49 | +[unix]: http://pubs.opengroup.org/onlinepubs/000095399/functions/exit.html |
| 50 | +[win]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682658%28v=vs.85%29.aspx |
| 51 | + |
| 52 | +This function is also not marked `unsafe`, despite the risk of leaking |
| 53 | +allocated resources (e.g. destructors may not be run). It is already possible |
| 54 | +to safely create memory leaks in Rust, however, (with `Rc` + `RefCell`), so |
| 55 | +this is not considered a strong enough threshold to mark the function as |
| 56 | +`unsafe`. |
| 57 | + |
| 58 | +# Drawbacks |
| 59 | + |
| 60 | +* This API does not solve all use cases of exiting with a nonzero exit status. |
| 61 | + It is sometimes more convenient to simply return a code from the `main` |
| 62 | + function instead of having to call a separate function in the standard |
| 63 | + library. |
| 64 | + |
| 65 | +# Alternatives |
| 66 | + |
| 67 | +* One alternative would be to stabilize `set_exit_status` as-is today. The |
| 68 | + semantics of the function would be clearly documented to prevent against |
| 69 | + surprises, but it would arguably not prevent all surprises from arising. Some |
| 70 | + reasons for not pursuing this route, however, have been outlined in the |
| 71 | + motivation. |
| 72 | + |
| 73 | +* The `main` function of binary programs could be altered to require an |
| 74 | + `i32` return value. This would greatly lessen the need to stabilize this |
| 75 | + function as-is today as it would be possible to exit with a nonzero code by |
| 76 | + returning a nonzero value from `main`. This is a backwards-incompatible |
| 77 | + change, however. |
| 78 | + |
| 79 | +* The `main` function of binary programs could optionally be typed as `fn() -> |
| 80 | + i32` instead of just `fn()`. This would be a backwards-compatible change, but |
| 81 | + does somewhat add complexity. It may strike some as odd to be able to define |
| 82 | + the `main` function with two different signatures in Rust. Additionally, it's |
| 83 | + likely that the `exit` functionality proposed will be desired regardless of |
| 84 | + whether the main function can return a code or not. |
| 85 | + |
| 86 | +# Unresolved questions |
| 87 | + |
| 88 | +* To what degree should the documentation imply that `rt::at_exit` handlers are |
| 89 | + run? Implementation-wise their execution is guaranteed, but we may not wish |
| 90 | + for this to always be so. |
0 commit comments