how do os.Exit() & deferred functions interact?

5,041 views
Skip to first unread message

Mark Summerfield

unread,
Dec 10, 2010, 3:31:26 AM12/10/10
to golang-nuts
Hi,

If I have this scenario (in pseudocode):

func main() {
defer atTheEnd()
someSuch()
}

func someSuch() {
os.Exit(1)
}

Does the exit happen immediately in someSuch() or does the deferred
atTheEnd() still end up being called?

Thanks!

--
Mark Summerfield, Qtrac Ltd, www.qtrac.eu
C++, Python, Qt, PyQt - training and consultancy
"Advanced Qt Programming" - ISBN 0321635906
http://www.qtrac.eu/aqpbook.html

Jessta

unread,
Dec 10, 2010, 3:48:27 AM12/10/10
to Mark Summerfield, golang-nuts
On Fri, Dec 10, 2010 at 7:31 PM, Mark Summerfield <li...@qtrac.plus.com> wrote:
> Hi,
>
> If I have this scenario (in pseudocode):
>
> func main() {
>    defer atTheEnd()
>    someSuch()
> }
>
> func someSuch() {
>    os.Exit(1)
> }
> Does the exit happen immediately in someSuch() or does the deferred
> atTheEnd() still end up being called?

"Deferred function calls are executed in LIFO order immediately before
the surrounding function returns, after the return values, if any,
have been evaluated, but before they are returned to the caller."
http://golang.org/doc/go_spec.html#Defer_statements

os.Exit(1) doesn't return, so someSuch() doesn't return, so main()
doesn't return so the
defer is never called.


- jessta

--
=====================
http://jessta.id.au

peterGo

unread,
Dec 10, 2010, 3:48:50 AM12/10/10
to golang-nuts
Mark,

For your scenario (in realcode):

package main

import (
"fmt"
"os"
)

func main() {
defer atTheEnd()
someSuch()
}

func someSuch() {
fmt.Println("someSuch")
os.Exit(1)
}
func atTheEnd() {
fmt.Println("atTheEnd")
}

os.Exit exits immediately.


Peter

Mark Summerfield

unread,
Dec 10, 2010, 4:18:53 AM12/10/10
to golan...@googlegroups.com
Thanks to you and Jessta...

of course I should have tried it in the sandbox:-)

However, I do think the os.Exit() docs might benefit from some addition.
At present the text is:

Exit causes the current program to exit with the given status code.
Conventionally, code zero indicates success, non-zero an error.

Maybe it could be added to---maybe something like:

Exit causes the current program to exit with the given status code.
Conventionally, code zero indicates success, non-zero an error.
On exit, any running goroutines are terminated and any allocated
memory is freed by the garbage collector. No pending deferred
statements are executed, so although any open files will be closed
by the Go runtime system, resources outside Go's control, such as
open database or network connections, will not be closed.

... if that's true of course.

--

Mark Summerfield, Qtrac Ltd, www.qtrac.eu

C++, Python, Qt, PyQt - training and consultancy

"Programming in Python 3" - ISBN 0321680561
http://www.qtrac.eu/py3book.html

--
Mark Summerfield, Qtrac Ltd, www.qtrac.eu

C++, Python, Qt, PyQt - training and consultancy

"Programming in Python 3" - ISBN 0321680561
http://www.qtrac.eu/py3book.html

Harald Schilly

unread,
Dec 10, 2010, 4:31:24 AM12/10/10
to golan...@googlegroups.com
On Friday, December 10, 2010 9:48:27 AM UTC+1, jessta wrote:

os.Exit(1) doesn't return, so someSuch() doesn't return, so main()
doesn't return so the defer is never called.


I've a related question, is there something like a shutdown hook in java? Would be quite ueseful (for database connections and such) to start a go routine after exit but before the program is acutally terminated.

Mark Summerfield

unread,
Dec 10, 2010, 4:45:02 AM12/10/10
to golan...@googlegroups.com
Hi,

Since os.Exit() exits immediately and no deferred statments can exit,
it seems to me that if you have at least one deferred statement (that
you want to be executed before termination) then there is no way to
return non-zero to the OS.

func main() {
...
defer closeMyDatabaseConnection() // this is vital
...
// uh oh something went wrong & I need to terminate with non-zero to
// indicate this, but I can't call os.Exit(2) because then my
// database connection will be left hanging.
}

Or is there something in the library I've missed that I could use?

Some languages have an atexit() function that can handle such
cases---does Go have something similar?

--
Mark Summerfield, Qtrac Ltd, www.qtrac.eu

C++, Python, Qt, PyQt - training and consultancy

roger peppe

unread,
Dec 10, 2010, 4:58:04 AM12/10/10
to Mark Summerfield, golan...@googlegroups.com
On 10 December 2010 09:45, Mark Summerfield <ma...@qtrac.eu> wrote:
> Hi,
>
> Since os.Exit() exits immediately and no deferred statments can exit,
> it seems to me that if you have at least one deferred statement (that
> you want to be executed before termination) then there is no way to
> return non-zero to the OS.
>
> func main() {
>    ...
>    defer closeMyDatabaseConnection() // this is vital
>    ...
>    // uh oh something went wrong & I need to terminate with non-zero to
>    // indicate this, but I can't call os.Exit(2) because then my
>    // database connection will be left hanging.
> }
>
> Or is there something in the library I've missed that I could use?

if you really wanted to do this, it would be straightforward;

var exitCode int
func exit() {
os.Exit(exitCode)
}
func main() {
defer exit()


defer closeMyDatabaseConnection() // this is vital

// uh oh something went wrong & I need to terminate with non-zero to
// indicate this

exitCode = 2
}

chris dollin

unread,
Dec 10, 2010, 5:05:42 AM12/10/10
to roger peppe, Mark Summerfield, golan...@googlegroups.com

or
defer func() { closeMyDatabaseConnection(); os.Exit( exitCode ) }

I think.

Chris

--
Chris "carthorse" Dollin

roger peppe

unread,
Dec 10, 2010, 5:23:58 AM12/10/10
to chris dollin, Mark Summerfield, golan...@googlegroups.com

sure. i was assuming the database closing could be in some other
function though.

Mark Summerfield

unread,
Dec 10, 2010, 5:40:42 AM12/10/10
to roger peppe, golan...@googlegroups.com
Hi Roger,

That's nice; I'll use that approach. Thanks!

--

Mark Summerfield, Qtrac Ltd, www.qtrac.eu
C++, Python, Qt, PyQt - training and consultancy

"Rapid GUI Programming with Python and Qt" - ISBN 0132354187
http://www.qtrac.eu/pyqtbook.html

Reply all
Reply to author
Forward
0 new messages