# Termination hook for handling error from \`main() -\> Result\<(), SomeError\>\`

**URL:** <https://internals.rust-lang.org/t/termination-hook-for-handling-error-from-main-result-someerror/13780>\
**Category:** libs\
**Created:** [January 8, 2021, 8:50pm UTC](https://internals.rust-lang.org/t/termination-hook-for-handling-error-from-main-result-someerror/13780 "2021-01-08T20:50:08Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![erickt](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/erickt/32/4498_2.png) [@erickt](https://internals.rust-lang.org/u/erickt)\
**Post date:** [January 8, 2021, 8:50pm UTC](https://internals.rust-lang.org/t/termination-hook-for-handling-error-from-main-result-someerror/13780/1 "2021-01-08T20:50:08Z")

</div>

Hello everyone,

On Fuchsia, most of our processes run in an environment where STDOUT and STDERR are redirected to an equivalent to /dev/null. Instead, we structure most of our components to emit logs to a central syslog service, which allows us to attach more structured data to each message. Overall this works well for us, except in the case of our [main functions returning Result::Err](https://doc.rust-lang.org/edition-guide/rust-2018/error-handling-and-panics/question-mark-in-main-and-tests.html). By default, the [`Termination` trait](https://doc.rust-lang.org/std/process/trait.Termination.html) just logs the error with `eprintln!()`, and so these messages get lost. Presumably other operating system services could run into this, such as if a linux service running under [systemd](https://manpages.debian.org/wheezy/systemd/systemd.exec.5.en.html) is set to run with:

```rust
...
StdoutOutput=null
StderrOutput=null
...

```

Has anyone explored creating an equivalent to [`std::panic::set_hook`](https://doc.rust-lang.org/stable/std/panic/fn.set_hook.html) for the `Termination` trait? It seems like it'd be a pretty easy RFC and feature to write up, especially since we have a precedent with `set_hook`. I'd be happy to start working on this, but I wanted to check here first if there has been prior art in this space. I couldn't find anything on [GitHub - rust-lang/rfcs: RFCs for changes to Rust](https://github.com/rust-lang/rfcs) or here.

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [January 8, 2021, 8:59pm UTC](https://internals.rust-lang.org/t/termination-hook-for-handling-error-from-main-result-someerror/13780/2 "2021-01-08T20:59:38Z")

</div>

What exactly is the benefit of using such a hook over simply keeping `main`’s return type `()` (or `ExitCode` once that’s stable; in the meantime using `process::exit` for nonzero exit codes) and handling the `Result` value directly?

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [January 8, 2021, 9:11pm UTC](https://internals.rust-lang.org/t/termination-hook-for-handling-error-from-main-result-someerror/13780/3 "2021-01-08T21:11:31Z")

</div>

+1 to @steffahn's points here.

This has come up in discussing whether to stabilize `Termination` too -- is it really better to implement the trait than to just have a macro for `main` or similar? (And just implementing a trait has way fewer questions than deciding what a hook should look like.)

To me, `main() -> Result<(), ...>` is like `dbg!` -- great for the simple cases, but it's totally expected that once one needs more control that something different is needed.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [January 8, 2021, 9:44pm UTC](https://internals.rust-lang.org/t/termination-hook-for-handling-error-from-main-result-someerror/13780/4 "2021-01-08T21:44:03Z")

</div>

> [@erickt](#):
>
> On Fuchsia, most of our processes run in an environment where STDOUT and STDERR are redirected to an equivalent to /dev/null. Instead, we structure most of our components to emit logs to a central syslog service, which allows us to attach more structured data to each message.

Out of curiosity, why not wire `stderr` up to that same log service? (systemd supports this by default, making it easy for programs to log by just printing to stderr.)

---

<div class="post-metadata">

**Author:** ![erickt](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/erickt/32/4498_2.png) [@erickt](https://internals.rust-lang.org/u/erickt)\
**Post date:** [January 8, 2021, 10:23pm UTC](https://internals.rust-lang.org/t/termination-hook-for-handling-error-from-main-result-someerror/13780/5 "2021-01-08T22:23:27Z")

</div>

Thanks for the comments.

The main reason I think it's worth exploring this problem space is that this is really easy for developers to trip over. Fuchsia is a large open source operating system with many binaries spread across multiple teams, and most of our developers are pretty experienced with Rust by now. That said, about 90 of our binaries use `main() -> Result<(), Error>` with our syslogger, and many of these callsites will silently drop the main function error results (for example, I fix a few in [http://fxrev.dev/468902](http://fxrev.dev/468902)). So this suggests to me that this might be a pretty common issue amongst applications that use some kind of a logger service.

On Fuchsia, while we could try to change our developer's habits by centrally ban the use of `main() -> Result<(), Error>`, and have them switch to macros, wrapper libraries, or etc. However, we are an open source OS, and so (hopefully) we'll have third party ecosystem developing applications for Fuchsia, and it would be a bit more difficult to help those developers avoid this issue. It'd be a lot easier and less error prone if we could address this issue for everyone by registering a termination hook.

Finally, I prototyped out my idea [GitHub - erickt/rust at termination-hook](https://github.com/erickt/rust/tree/termination-hook) if you want to see it in action. I'm not sure if this is _quite_ the right approach if we ever end up stabilizing the `Termination` trait, since it's only wired up to work with the `Result` type. Presumably we'd want something more like `PanicInfo` which could work with all `Termination` implementations.

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [January 8, 2021, 10:55pm UTC](https://internals.rust-lang.org/t/termination-hook-for-handling-error-from-main-result-someerror/13780/6 "2021-01-08T22:55:36Z")

</div>

Hm, some of the examples in the commit you linked even _have_ some special procedural macros on them already to handle `async`. Those could perhaps be modified in order to also capture the return value and properly log it, right?

Also, every example in this commit seems to first do some form of call for initializing logging. This call could possibly be included in a non-async version of the macro, too, so there would even be more benefits beyond just fixing the main-return-value handling.

In don't think that requiring everyone to either use a macro or return `()` is too hard or confusing.

---

<div class="post-metadata">

**Author:** ![erickt](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/erickt/32/4498_2.png) [@erickt](https://internals.rust-lang.org/u/erickt)\
**Post date:** [January 8, 2021, 11:23pm UTC](https://internals.rust-lang.org/t/termination-hook-for-handling-error-from-main-result-someerror/13780/7 "2021-01-08T23:23:49Z")

</div>

> [@josh](#):
>
> Out of curiosity, why not wire `stderr` up to that same log service? (systemd supports this by default, making it easy for programs to log by just printing to stderr.)

Fuchsia is a capability based operating system, and so we lean heavily into the Principle of Least Privilege. As part of that, we're trying to minimize as much functionality as possible in our component manager (which I suppose is somewhat analogous to systemd's service manager).

Our system logger isn't a first class service that's built into component manager, but instead is just a normal service that that has a capability to communicate to it that's routed to most components. So communicating with the system logger needs to be done inside the process. Furthermore, we don't have a notion of a STDOUT/STDERR in our component model, so any communication with the system logger has to be done in-process. We are exploring how we might want to support this, but we're still pretty early on in the design of that.

But even if we did have the ability to route standard I/O to our system logger, it still might be advantageous to have a termination hook. We are working towards adding structured log messages to our system logger, so it would be handy to use a hook to capture that information, rather than just getting raw strings with STDERR.

---

<div class="post-metadata">

**Author:** ![erickt](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/erickt/32/4498_2.png) [@erickt](https://internals.rust-lang.org/u/erickt)\
**Post date:** [January 8, 2021, 11:30pm UTC](https://internals.rust-lang.org/t/termination-hook-for-handling-error-from-main-result-someerror/13780/8 "2021-01-08T23:30:16Z")

</div>

> [@steffahn](#):
>
> Hm, some of the examples in the commit you linked even _have_ some special procedural macros on them already to handle `async` . Those could perhaps be modified in order to also capture the return value and properly log it, right?

Yeah, it definitely is a possibility to use a wrapper, and actively encourage people to use it. I posted about this hear mainly because we happened to perform a natural experiment to reveal how easy it was to miss this issue. I wanted to explore here if other people have had this problem, and if we thought this was something we might want to try to address holistically, rather than in a case-by-case manner.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [April 8, 2021, 11:30pm UTC](https://internals.rust-lang.org/t/termination-hook-for-handling-error-from-main-result-someerror/13780/9 "2021-04-08T23:30:21Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
