How to return exit code from the main() function?

Is using os.exit() the only way to return the exit code? If I use os.exit() in main() then defer cannot be used because of the following error:

Error: Unreachable defer statement due to diverging procedure call at the end of the current scope

The following GitHub Discussion proposes this solution:

Main procedures in Odin can’t return a value? - GitHub Discussion

If you want to emulate something like int main() from C, for example, you can define another proc like run which does return a value. Then all your main does is call that function, and handle any error it returned accordingly - using os.exit() to abort with an exit code, or whatever you would like your specific application to do.

Is there any other way to return the exit code from main() so that return, defer, and other control flow works normally.

1 Like

Also, the usage of os.exit() affects the execution of @(fini) blocks. From os.exit() docs:

os.exit - (pkg.odin-lang.org)

IMPORTANT: @(fini) blocks won’t be executed.
If you want @(fini) cleanup to happen, call runtime._cleanup_runtime first.

This way you can use os.exit and have return, defer, exit code(s), @fini block(s):

package main

import "base:runtime"
import "core:os"
import "core:fmt"

exit_code: int
main :: proc() {
	defer fmt.println("deferred message")
	if condition {
		exit_code = 5
		return
	} else {
		exit_code = 1
	}
	fmt.println("random message")
}

@fini
shutdown :: proc "contextless" () {
	context = runtime.default_context()
	fmt.println("Terminating the program.")
	os.exit(exit_code)
}
1 Like

You put the fallible code into a function, no reason to mess with main directly.


resource: ^Resource

main_impl :: proc() -> (err: Error) {
    // ... 
}

main :: proc() {
    err: Error
    defer if err != nil do os.exit(1)

    {
        // Instead of .fini
        resource = alloc()
        defer release(resource)

        err = main_impl()
    }
}

This is usually the same pattern you’d use to setup custom allocator/logger for different modes (e.g. debug) and never touch the implementation itself. It also makes sure that Odin runtime is usable.

2 Likes