go: os: Exit does not respect deferred functions making any cleanup code useless
What version of Go are you using (go version)?
$ go version go version go1.14.1 windows/amd64
Does this issue reproduce with the latest release?
yes
What operating system and processor architecture are you using (go env)?
go env Output
set GO111MODULE=auto set GOARCH=amd64 set GOBIN= set GOCACHE=C:\Users\anonymous\AppData\Local\go-build set GOENV=C:\Users\anonymous\AppData\Roaming\go\env set GOEXE=.exe set GOFLAGS= set GOHOSTARCH=amd64 set GOHOSTOS=windows set GOINSECURE= set GONOPROXY= set GONOSUMDB= set GOOS=windows set GOPATH=C:\Users\anonymous\go set GOPRIVATE= set GOPROXY=https://proxy.golang.org,direct set GOROOT=c:\go set GOSUMDB=sum.golang.org set GOTMPDIR= set GOTOOLDIR=c:\go\pkg\tool\windows_amd64 set GCCGO=gccgo set AR=ar set CC=gcc set CXX=g++ set CGO_ENABLED=1 set GOMOD=C:\Users\anonymous\Desktop\an\go.mod set CGO_CFLAGS=-g -O2 set CGO_CPPFLAGS= set CGO_CXXFLAGS=-g -O2 set CGO_FFLAGS=-g -O2 set CGO_LDFLAGS=-g -O2 set PKG_CONFIG=pkg-config set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0 -fdebug-prefix-map=C:\Users\anon~1\AppData\Local\Temp\go-build078526234=/tmp/go-build -gno-record-gcc-switches
What did you do?
I called os.Exit(1) on SIGINT https://play.golang.org/p/_Py0WToAf8v (Local testing is better, playground does not like sleeps and have no way to cause a SIGINT).
What did you expect to see?
Golang runs all deferred cleanup routines. This would allow every go routine to register it’s own cleanup function if you think separation of concerns is a thing.
What did you see instead?
No Cleanup function is called at all, but that is important if you’re writing to files in other goroutines. Panic have a similiar issue.
See also: #4101
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 1
- Comments: 17 (3 by maintainers)
@ccbrown I already explained the use case. And I think contexts are not applicable because you can’t interrupt sleeping goroutines. What about blocking file operations for example.
If you look at my example, you will see that Cancelation won’t work here as the main routine is not able to cancel the goroutine (the process exit is triggered by the goroutine itself). I’m not sure how you get separation of concerns with contexts, because my idea is, that everyn goroutine should be responsible for the cleanup it must do (btw this makes code a lot more understandable und reusable, because you haven’t any hidden dependencies with other code pieces that have to do cleanup for goroutines in the case of an early exit). And as far as I can remember the
defercall was advertised for cleanup tasks. Which, as we can see is not a reliable way if the application panics or if the process is killed. See my example on playground.And I think it’s a common task to do some cleanup if the user interrupts the process with SIGINT before exiting. The other way arround I’m question myself why we have os.Exit if it’s not applicable to reliable close a process. It does not respect defers. Some of go’s core features.
@ccbrown most of the other languages have other methods ensuring that cleanup code can run on a call to exit. This doesn’t necessary have to happen inside a destructor (or a defer call) but it would make things much less annoying. An example in C++ is
atexit. I don’t know a similiar golang mechanism. And saying, no language did this that way is not a really good reason for not doing it. Golang does many things other languages do not do. And as far as I can remember a simliar policy applies for stuff people want golang to have.