My team is publishing a Go shared library containing our business logic, with wrappers in several other languages. We’re having a problem on Windows only where user signal handlers do not get invoked if they import our library. For example, in Python:
from signal import signal, SIGINT # import our library here (or anywhere below; order makes no difference) def handler(signal_received, frame): print('Cleaning up') exit(0) if __name__ == '__main__': signal(SIGINT, handler) print('Running. Press CTRL-C to exit.') # Main loop goes here.
The use case for this is to shut down equipment automatically when someone stops the controlling script.
From this ticket and from looking at the Go source code, it looks like Go always installs its own handler for SIGINT on Windows, which just kills the program when CTRL-C is pressed.
I can use
signal.Ignore(os.Interrupt) to disable that, but it doesn’t restore the default handler. I can use
signal.Notify(channel, os.Interrupt) to handle the signal in our Go code, but re-raising it via a CGo function in our Go handler just creates an infinite loop.
I could invoke a callback in the user language that would raise the signal over there, but that will not cause the user’s handler to be invoked automatically - I tested this by adding
os.kill(os.getpid(), signal.SIGABRT) to the Python example above.
That leaves me with creating API for users to provide a callback specific to this purpose, which is inelegant because the expectation is that they should be able to use their language’s own facilities for this.
So far I have not spotted a way to make Go leave the SIGINT handler alone or restore the original one. There is a Windows-specific note at the bottom of the signal documentation that basically says your options are hard exit or handling it in Go.
Is anyone aware of some option to allow other-language signal handlers to still work on Windows?