Skip to content

runtime.Goexit cancels pending defer commands -- bug or documentation error? #349

@gopherbot

Description

@gopherbot

by mzraly:

What steps will reproduce the problem?
1. Run this program:

package main

import (
        "fmt";
        "runtime";
)

func CallGoexit() {
        fmt.Println("enter CallGoexit");
        defer fmt.Println("leave CallGoexit");
        runtime.Goexit();
}

func main() { CallGoexit() }

What is the expected output? What do you see instead?

Expected to see:
enter CallGoexit
leave CallGoexit

Instead just saw:
enter CallGoexit

What is your $GOOS?  $GOARCH?

GOOS=linux
GOARCH=386

Which revision are you using?  (hg identify)

[~/go]% hg identify
cf1a9b1f9bee tip

Please provide any additional information below.

It is unclear to me whether or not this is a bug in the go runtime. 
Neither the language spec nor the package documentation for runtime.Goexit
mention whether or not pending defer blocks are executed after the call to
runtime.Goexit.

In some cases it would certainly be convenient for defer blocks to be
executed after the call to runtime.Goexit.  This would provide a trivial
mechanism for ensuring prompt release of resources and for type-safe
transmission of data to other goroutines.  In particular, it would help for
cases where a goroutine acquires a resource handle (e.g. a database
transaction handle or cursor), calls untrusted processing code, then
releases the handle.  If the untrusted processing code calls Goexit() then,
in the current implementation, the resource handle cannot be released.

There are a couple of alternatives to using defer blocks to notify callers
of goroutine termination:

GC finalizers (once implemented) can be used to release resource handles
and send data to other goroutines eventually, provided the finalizers are
guaranteed to run if the program does not crash.  However there is no
telling when a particular finalizer will run in a long-running program.

Another alternative would be to create a separate server goroutine for each
resource that accepts commands to manipulate the resource and which has a
timeout after which it will release the resource and cease operation.  This
requires an extra goroutine per resource and requires users to determine
what timeout value to use.

Neither alternative is truly satisfactory.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions