Cleanly exiting the program in Rust


#1

There was a similar thread here but I don’t want to necrobump.

Currently, we only have std::process::exit(). It does exactly what its name does - exits. Without cleaning up anything. In particular, without calling destructors.

In some programming cases, we may find out that we have no more work to do and just need to exit. This may happen very deep in the call tree. The currently possible solutions, which came up in a discussion on IRC, are:

  1. Use std::process::exit. This, as said before, invokes no destructors and may be a source of bugs. There’s no use duplicating code and writing custom cleanup functions (which do exactly the same as the Drop trait) and at some time forget that we have this buffered logger in completely separate part of code we forgot about, or a created temporary file we were to delete, or some Unix socket we wanted to delete, …
  2. Propagate the “end of program” condition. Here, if we use Result - we create nonsense in our code, using the Err variant for cases where no error has occurred. If use something else, e.g. an enum, we can’t simply use the try! or ? macro, so we clutter the code at any exit point. Of course, we can write our own, make it a crate, … And what if we were using Command::new to launch a command and just want to exit with the child’s exit code… std::process::exit at the last line…?

But remember, we were just to exit the program. And this is not an error, no exception - just time to finish our work.

I perfectly know that stack unwinding is very costly in Rust - but the program is going to terminate anyway in a while, so I don’t find it a big problem in this case. It is the whole power of destructors that they get invoked without the programmer having not to forget about them.

Is this a design decision not to support exit with unwinding or is it just something that is planned for future releases?


#2

What do you want to have happen to threads other than the main one when this happens?


#3

I see that panic! properly unwinds the stack, even with multiple threads. What’s the panic!'s policy here?

I think that this unwindive exit could do the same.


#4

A panic unwinds the stack of the thread it occurred on, after which that thread the exits. If the main thread exits, the program terminates.


#5

Small note, panic may unwind the stack. It may also abort.


#6

What with the other threads?

Sometimes the whole process just gets killed: https://play.rust-lang.org/?gist=8f46c76c07bd49b4790f2c2c23136fe1&version=stable but I don’t know if it’s a general rule with multiple threads.


#7

Yep, I know, this can be set at compilation time. I meant the default panic behavior.


#8

A panic in one thread does not affect other threads.


#9

Ok, but in my example a panic in one thread killed all the others.


#10

It looks like that program hits the playground timeout when I run it.


#11

So why not do the same for the “clean exit”? And the exitcode would be the exitcode from the main thread.


#12

Panic also aborts in the case of double panics, not only when panic=abort is set.


#13

In fact, the C exit function will do some cleanup: http://en.cppreference.com/w/c/program/exit


#14

The C exit function will do some internal cleanup of the C standard library’s internal stuff, such as flushing the C standard library stdout buffer, as well as calling any handlers registered via atexit. It will not do any cleanup of Rust destructors.