63

I am in the process of writing a bash clone in Rust. I need to have my program exit when the user types exit. In previous iterations of my program, before I added more complicated features, I used return to get out of the loop that was prompting the user for input. This logic is now in a function, because of the way I am implementing built in shell functions, so when I return it just jumps out of the function back into the control loop, instead of short-circuiting the control loop and ending the program.

I realize that I could probably return a boolean when the user types exit and exit the loop, but I would like to at least know if Rust has a way to terminate programs early, similar to Java's System.exit(), as this is useful for certain types of programs.

1
  • 1
    No, there is no safe way to terminate a Rust program early. Causing every task to unwind completely (either by returning or by failing) is the only way. Commented Feb 6, 2014 at 0:35

2 Answers 2

90

Rust 1.0 stable

std::process::exit() does exactly that - it terminates the program with the specified exit code:

use std::process;

fn main() {
    for i in 0..10 {
        if i == 5 {
            process::exit(1);
        }
        println!("{}", i);
    }
}

This function causes the program to terminate immediately, without unwinding and running destructors, so it should be used sparingly.

Alternative (not recommended) solution

You can use C API directly. Add libc = "0.2" to Cargo.toml, and:

fn main() {
    for i in 0..10 {
        if i == 5 {
            unsafe { libc::exit(1); }
        }
        println!("{}", i);
    }
}

Calling C functions cannot be verified by the Rust compiler, so this requires the unsafe block. Resources used by the program will not be freed properly. This may cause problems such as hanging sockets. As far as I understand, the proper way to exit from the program is to terminate all threads somehow, then the process will exit automatically.

Sign up to request clarification or add additional context in comments.

6 Comments

I tried this and it works. It would be nice if there is a way to do this through Rust instead of through the C library, though. Thanks!
Using libc::exit is a bad idea. It does not terminate the process cleanly and may break things dangerously. Normal Rust process conclusion must involve stack unwinding so that destructors are called, while exit(3)'s approach to concluding is quite different and does not involve stack unwinding. Thus, if you have things like open files, they may not be flushed and closed, TCP bound sockets may not be properly released (meaning you can't bind to the socket until a timeout expires, probably a minute or so), &c.—the libc::exit is basically equivalent to a segfault, not a clean exit.
@ChrisMorgan, yes, I was expecting something like that. But I couldn't find another way. Does Rust provide a way to terminate current task cleanly, without a fail? Or another way to stop the process? edit: oh, sorry, didn't see your comment to the question. That's a pity...
@ChrisMorgan Socket binding is handled by the OS; once you exit, it cleans up. You can re-bind immediately. File buffers not being flushed is indeed valid, though.
@VladimirMatveev I get a compile error when using exit() any idea why? src\main.rs:14:27: 14:28 error: expected type, found 1 src\main.rs:14 std::process:exit(1);
|
4
panic!("Oh no something bad has happened!")

Example:

    if a * g < 0f32 { panic!("The arithmetric-geometric mean is undefined for numbers less than zero!"); }

In older documentation, you will see this as fail!("Oh no something bad here has happened.")

For some reason, this macro was changed from fail to panic. Panic is the way to fail, if you must.

[edit] I am sorry. It looks like you should be testing input for the string "exit," which would depend on how you are taking input (by line or by args). Then you can have the program break out of the loop on the condition that the exit is detected.

Example:

loop {
    if exit_found { break }
    else {
        // your thing, which also looks for exit_found
    }
}

2 Comments

Note that all panic! does is gracefully terminate the current task. If the function isn't currently on the main task then the panic! won't exit the program. And even if it is, it's not the same as exit, since panic! will run the destructors with arbitrary code.
fail! was re-named to panic! in this RFC: github.com/rust-lang/rfcs/blob/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.