Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

runtime: Go program built as a DLL kills the application with exit code 2 due to signal handler #35965

Closed
martinzak-zaber opened this issue Dec 4, 2019 · 4 comments

Comments

@martinzak-zaber
Copy link
Contributor

@martinzak-zaber martinzak-zaber commented Dec 4, 2019

What version of Go are you using (go version)?

$ go version
go version go1.13.4 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
$ go env
set GOARCH=386
set GOBIN=
set GOCACHE=C:\Users\martin\AppData\Local\go-build
set GOEXE=.exe
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOOS=windows
set GOPATH=C:\Users\martin\go
set GOPROXY=
set GORACE=
set GOROOT=c:\go
set GOTMPDIR=
set GOTOOLDIR=c:\go\pkg\tool\windows_amd64
set GCCGO=gccgo
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=
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\martin\AppData\Local\Temp\go-build385488510=/tmp/go-build -gno-record-gcc-switches

What did you do?

We use go to build a windows DLL that we later load in various environments (Python, C#, Node.js).

Our issue is caused by the behaviour of the signal handler ctrlhandler1 in src/runtime/os_windows.go. If the signal is not handled in go environment the handler calls exit(2) killing the entire application. That may be desired when go program is an application. However, in the case of DLL the behavior prevents other handlers registered through SetConsoleCtrlHandler to run (e.g. the one registered by Python) killing the entire application instead (with exit code 2). Registering the signal handler in go is not an option as this prevents other handlers to run completely by returning true (signal handled) in ctrlhandler1.

Here is an example of a go program build as a DLL and a Python script that loads the DLL. The handler in the Python script never gets called due to go killing the application. We have the same issue with all other environments (like Node.js). We have also prepared a little zip with reproduction downloadable here: go_repro.zip

package main

import "C"

import (
	"fmt"
	"time"
)

func libCounter() {
	count := 0
	for {
		fmt.Println("Count: ", count)
		count++
		time.Sleep(time.Second)
	}
}

//export Start
func Start() {
	go libCounter()
}

func main() {
}
from ctypes import *
from signal import signal, SIGINT
import time

lib = cdll.LoadLibrary(".\\lib.dll")

def handler(signal_received, frame):
    print('Yay! Python signal handler!')
    exit(0)


signal(SIGINT, handler)

print("Starting from Python main loop. Press CTRL-C end stop.")
lib.Start()

while True:
    time.sleep(0.25)
    pass

It is worth noting that we don't have the same issue under Linux or Mac OS.
We, unfortunately, cannot come up with any workaround like changing handlers order or removing go's handler completely. Our only option as of now is to build the DLL with a modified go compiler.
We appreciate suggestions to work around this as much as a possible change of the behavior. Possibly the runtime would not exit(2) when building as a DLL if that is possible and viable.

Thank you for examining our issue.

What did you expect to see?

Starting from Python main loop. Press CTRL-C end stop.
Count:  0
Count:  1
Count:  2
Yay! Python signal handler!
exit code: 0

What did you see instead?

Starting from Python main loop. Press CTRL-C end stop.
Count:  0
Count:  1
Count:  2
exit code: 2
@ianlancetaylor ianlancetaylor changed the title Go program built as a DLL kills the application with exit code 2 due to signal handler runtime: Go program built as a DLL kills the application with exit code 2 due to signal handler Dec 4, 2019
@ianlancetaylor ianlancetaylor added this to the Go1.15 milestone Dec 4, 2019
@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Dec 4, 2019

@alexbrainman
Copy link
Member

@alexbrainman alexbrainman commented Dec 6, 2019

Possibly the runtime would not exit(2) when building as a DLL if that is possible and viable.

I agree, we should do that. This issue is similar to recent

https://go-review.googlesource.com/c/go/+/181839

where Go DLL would crash whole process when handling exception.

@martinzak-zaber do you want to send appropriate change? This

https://golang.org/doc/contribute.html

is how to contribute.

Alex

@martinzak-zaber
Copy link
Contributor Author

@martinzak-zaber martinzak-zaber commented Dec 6, 2019

It will be a pleasure to provide that fix.

We will get back to you in the following week.

Thank you.

Zaber Software Team

@gopherbot
Copy link

@gopherbot gopherbot commented Dec 13, 2019

Change https://golang.org/cl/211139 mentions this issue: runtime: Fixing OS Windows signal handler behavior for libraries

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

4 participants
You can’t perform that action at this time.