-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
os, runtime: CTRL_CLOSE_EVENT should generate SIGTERM on Windows #7479
Comments
fyi, after applying [1] and doing dev tests it looks like CTRL_CLOSE_EVENT can only be received for a console process in Windows 7 when using some nasty hacks [2]. Pre Win7 the event seems receivable. If desired I would test it under Win8+. Or did I miss anything obvious in my diff? [1] https://gist.github.com/sgeller/10196571 [2] http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/abf09824-4e4c-4f2c-ae1e-5981f06c9c6e/windows-7-console-application-has-no-way-of-trapping-logoffshutdown-event?forum=windowscompatibility |
Comment 2 by anacrolix@google.com: That's strange it works for me and I'm using Windows 7 32bit. From the thread it looks like the big spanners you can throw in are: * Your app is a GUI/full-fledge Win32 app (this requires a flag to the go linker). * You're invoking other Win32 APIs such as service-related and event-loop related stuff. None of the above were true in my testing. The patch you want is https://codereview.appspot.com/download/issue71900043_40001.diff Your gist generates SIGINT for CTRL_CLOSE_EVENT which isn't optimal, the patch generates SIGTERM for reasons given in the source. Either way you must also catch the signal with os.Notify. There's a test program here: https://bitbucket.org/anacrolix/dms/src/8d6ab94e3c8032d11b870867609ba9dd618e79fc/play/termsig/?at=default If you pipe the output to a file from a terminal, and then close the terminal you should see the termination signal in the file. |
FYI // I have just been having a discussion about this with some guys in one of the Go Google groups because I was looking for a solution to catch the console being closed (on Windows) while a Go app is running. This is the discussion: https://groups.google.com/forum/#!topic/golang-nuts/S_RDVG3lcdI Java appears to be handling this in a sensible way by listening for CLOSE and SHUTDOWN events then firing a SIGTERM signal: http://hg.openjdk.java.net/jdk9/dev/hotspot/file/9b3f5e4f3372/src/os/windows/vm/os_windows.cpp#l1883 It would be really helpful if this could be implemented in Go. |
I am happy to try and implement this functionality (after go1.4 is released), but I need some input: - which extra events we should handle? - which syscall or os signals these new events should me mapped into? I have very little experience with these, and I don't want to influence that decision. Alex |
So is this issue effectively dead? It would be great to be able to handle certain windows-specific signals. |
The issue is not dead, but I'm not aware of anybody working on it. |
@alaska what are you trying to do? Alex |
To detect (as best as I can) when the window is closed on a console application. No matter how it's represented internally, CTRL_CLOSE_EVENT is useful to capture so that cleanup actions can be performed, like flushing to disk or gracefully disconnecting from a service in the 5 seconds allotted after the signal is sent. |
Thank you. I will try and implement this once Go source tree opens again. Unless you want to do it yourself. Alex |
I'd be happy to, though I would like a collaborator or owner to have the final say on what it maps to, though SIGTERM does seem reasonable. |
I really don't know. I suggest we go with SIGTERM. Others will correct us, if they want to. Alex |
+1 to SIGTERM |
I tried implementing this (windows-386 only):
and the only way I can stop Windows closing my process is by not returning from ctrlhandler1 (see usleep I have inserted there). This way everything works as expected - I get new signal and can act on it as I wish. Unfortunately my change has one bad side effect. I cannot close console window with my process running in it now (unless I have Go SIGTERM handler doing exiting explicitly). We cannot have this change of default behaviour. I don't see how we can overcome this. Alex |
I'm thinking, this issue is how to handle SIGTERM on windows using CTRL_CLOSE_EVENT.So it should be a default behavior if the if the user does not catch SIGTERM. |
But none of my programs handle SIGTERM. Sorry @mattn, but I don't like that suddenly all my Go programs won't allow me to close console window. We have to find a way around this problem. Alex |
To handle control events, one can register a Control Handler Function which can be easily done syscalls. SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE); Is there a reason why nobody has suggested that? |
Go runtime uses SetConsoleCtrlHandler to handle CTRL_C_EVENT and CTRL_BREAK_EVENT events. (grep runtime package for SetConsoleCtrlHandler). I don't understand why someone has to suggest to use SetConsoleCtrlHandler. Alex |
Can we please have a way to catch |
Did you see #7479 (comment) ? I suspect you will have the same problem with CTRL_SHUTDOWN_EVENT. Feel free to try it yourself. Alex |
@alexbrainman if I understand correctly, the problem lies into making sure that Potentially naive pseudo code: func ctrlhandler1(_type uint32) uint32 {
switch _type {
case _CTRL_C_EVENT, _CTRL_BREAK_EVENT:
if !sigsend(_SIGINT) {
exit(2) // Signal processing failed.
}
return 1 // Disallow default processing to not terminate the process.
case CTRL_CLOSE_EVENT:
if !sigsend(_SIGTERM) {
exit(2) // Signal processing failed.
}
signalWaitUntilIdle()
return 1 // Windows will terminate the process forcibly.
default:
return 0 // Default handler will terminate the process.
}
} |
@alexbrainman I did see it, but I was looking for an out-of-the-box solution. i.e. I do not want to compile my own version of go. Maybe we can get around this without re-compiling go? Maybe by calling |
@maruel the problem with my change from #7479 (comment) is that it requires every single Go program to handle SIGTERM. For example, if I run this program
in a Windows command window, and then click
Maybe it will, but I don't see how.
@rgl I did not try calling SetConsoleCtrlHandler from Go. Alex |
@alexbrainman I tried with the following snippet, but for some reason, the callback is never called (altough the CTRL+C shortcut stops working). Do you have any idea why its not working? package main
import (
"log"
"time"
"syscall"
"golang.org/x/sys/windows"
)
func main() {
kernel32 := windows.NewLazySystemDLL("kernel32.dll")
setConsoleCtrlHandler := kernel32.NewProc("SetConsoleCtrlHandler")
r1, r2, lastErr := setConsoleCtrlHandler.Call(
syscall.NewCallback(func(controlType uint) uint {
log.Printf("consoleControlHandler called with %v", controlType)
panic("ops")
return 0
}),
1)
log.Printf("call result %v %v %v", r1, r2, lastErr)
for {
time.Sleep(1 * time.Second)
}
} |
works on win10 32bit golang program
|
@rgl sorry I misplaced your question. I just checked your example works fine with current version of Go - both 64 and 32 bit. But it was broken at around the time you asked your question (Apr 8, 2018). I bisected the history to this change bb0fae6 Alex |
A workaround, based on previous comments:
When I want to block waiting for signals:
Exiting As to the issue: I'm not sure I agree with translating these to I'm not really sure how to implement these, and not really an expert in any of this. Just my 2¢. |
@alexbrainman, when you say nothing happens, does that mean the program is not forcibly closed after the 5s allowed for cleanup? Or just that it takes 5s to close? Also, is it possible to know whether an handler was installed for a certain signal? If so, and if new signals are created to represent I still think |
I am away from my computer for few weeks. But, as far as I remember, I could not close cmd window at all.
I would not know. Go uses SetConsoleCtrlHandler Windows API. You can google for SetConsoleCtrlHandler documentation to see what is possible and what is not. Alex |
Thanks @alexbrainman for taking the time to answer. I think you misunderstood me on my second point? Let me try again. I agree with you that it is not good to change behavior (hanging every process is bad, even if only for 5s). However, if the user registers to receive the signal at the Go level (so So, is it possible to know, generally, if the user is interested in a particular signal? This also rests on the assumption that ia new signal (or signals) is used, to indicates to the user that he has only a few seconds to terminate the process (can't be cancelled, and you don't get a second chance to handle them). Thanks again. |
But my example from before ( #7479 (comment) ) does not have any
I would not know. Go uses SetConsoleCtrlHandler Windows API. You can google for SetConsoleCtrlHandler documentation to see what is possible and what is not. Alex |
…VENT This is part of the changes necessary to allow simulated `SIGTERM` on Windows (these are the relevant events for `SetConsoleCtrlHandler` that would correspond to `SIGTERM` on Unix). Updates golang/go#7479
…VENT This is part of the changes necessary to allow simulated `SIGTERM` on Windows (these are the relevant events for `SetConsoleCtrlHandler` that would correspond to `SIGTERM` on Unix). See https://docs.microsoft.com/en-us/windows/console/handlerroutine for a good documentation source upstream to confirm these values. Updates golang/go#7479
Change https://golang.org/cl/187578 mentions this issue: |
…VENT This is part of the changes necessary to allow simulated `SIGTERM` on Windows (these are the relevant events for `SetConsoleCtrlHandler` that would correspond to `SIGTERM` on Unix). See https://docs.microsoft.com/en-us/windows/console/handlerroutine for a good documentation source upstream to confirm these values. Updates golang/go#7479 (This exists under `src/cmd/vendor/golang.org/x/sys/windows/types_windows.go` in https://github.com/golang/go, so I figured I would start here and follow up with a https://github.com/golang/go PR/CL if reviewers here were amenable to this half.) Change-Id: If3d0175bb889e4eddca838ef765faf5e379285ea GitHub-Last-Rev: 7db84d6 GitHub-Pull-Request: #37 Reviewed-on: https://go-review.googlesource.com/c/sys/+/187578 Reviewed-by: Alex Brainman <alex.brainman@gmail.com> Run-TryBot: Alex Brainman <alex.brainman@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
…NT as SIGTERM on Windows This matches the existing behavior of treating CTRL_C_EVENT, CTRL_BREAK_EVENT as a synthesized SIGINT event. See https://docs.microsoft.com/en-us/windows/console/handlerroutine for a good documentation source upstream to confirm these values. As for the usage of these events, the "Timeouts" section of that upstream documentation is important to note, especially the limited window in which to do any cleanup before the program will be forcibly killed (defaults typically 5s, but as low as 500ms, and in many cases configurable system-wide). These events are especially relevant for Windows containers, where these events (particularly `CTRL_SHUTDOWN_EVENT`) are one of the only ways containers can "gracefully" shut down (moby/moby#25982 (comment)). This also updates the vendoring of "golang.org/x/sys" under "cmd" to include CL 187578 (adding these same symbols). Fixes golang#7479
Change https://golang.org/cl/187739 mentions this issue: |
…NT as SIGTERM on Windows This matches the existing behavior of treating CTRL_C_EVENT, CTRL_BREAK_EVENT as a synthesized SIGINT event. See https://docs.microsoft.com/en-us/windows/console/handlerroutine for a good documentation source upstream to confirm these values. As for the usage of these events, the "Timeouts" section of that upstream documentation is important to note, especially the limited window in which to do any cleanup before the program will be forcibly killed (defaults typically 5s, but as low as 500ms, and in many cases configurable system-wide). These events are especially relevant for Windows containers, where these events (particularly `CTRL_SHUTDOWN_EVENT`) are one of the only ways containers can "gracefully" shut down (moby/moby#25982 (comment)). This was verified by making a simple `main()` which implements the same code as in `ExampleNotify_allSignals` but in a `for` loop, building a `main.exe`, running that in a container, then doing `docker kill -sTERM` on said container. The program prints `Got signal: SIGTERM`, then exits after the aforementioned timeout, as expected. Behavior before this patch is that the program gets no notification (and thus no output) but still exits after the timeout. Fixes golang#7479
…NT as SIGTERM on Windows This matches the existing behavior of treating CTRL_C_EVENT, CTRL_BREAK_EVENT as a synthesized SIGINT event. See https://docs.microsoft.com/en-us/windows/console/handlerroutine for a good documentation source upstream to confirm these values. As for the usage of these events, the "Timeouts" section of that upstream documentation is important to note, especially the limited window in which to do any cleanup before the program will be forcibly killed (defaults typically 5s, but as low as 500ms, and in many cases configurable system-wide). These events are especially relevant for Windows containers, where these events (particularly `CTRL_SHUTDOWN_EVENT`) are one of the only ways containers can "gracefully" shut down (moby/moby#25982 (comment)). This was verified by making a simple `main()` which implements the same code as in `ExampleNotify_allSignals` but in a `for` loop, building a `main.exe`, running that in a container, then doing `docker kill -sTERM` on said container. The program prints `Got signal: SIGTERM`, then exits after the aforementioned timeout, as expected. Behavior before this patch is that the program gets no notification (and thus no output) but still exits after the timeout. Fixes golang#7479
…NT as SIGTERM on Windows This matches the existing behavior of treating CTRL_C_EVENT, CTRL_BREAK_EVENT as a synthesized SIGINT event. See https://docs.microsoft.com/en-us/windows/console/handlerroutine for a good documentation source upstream to confirm these values. As for the usage of these events, the "Timeouts" section of that upstream documentation is important to note, especially the limited window in which to do any cleanup before the program will be forcibly killed (defaults typically 5s, but as low as 500ms, and in many cases configurable system-wide). These events are especially relevant for Windows containers, where these events (particularly `CTRL_SHUTDOWN_EVENT`) are one of the only ways containers can "gracefully" shut down (moby/moby#25982 (comment)). This was verified by making a simple `main()` which implements the same code as in `ExampleNotify_allSignals` but in a `for` loop, building a `main.exe`, running that in a container, then doing `docker kill -sTERM` on said container. The program prints `Got signal: SIGTERM`, then exits after the aforementioned timeout, as expected. Behavior before this patch is that the program gets no notification (and thus no output) but still exits after the timeout. Fixes golang#7479
…NT as SIGTERM on Windows This matches the existing behavior of treating CTRL_C_EVENT, CTRL_BREAK_EVENT as a synthesized SIGINT event. See https://docs.microsoft.com/en-us/windows/console/handlerroutine for a good documentation source upstream to confirm these values. As for the usage of these events, the "Timeouts" section of that upstream documentation is important to note, especially the limited window in which to do any cleanup before the program will be forcibly killed (defaults typically 5s, but as low as 500ms, and in many cases configurable system-wide). These events are especially relevant for Windows containers, where these events (particularly `CTRL_SHUTDOWN_EVENT`) are one of the only ways containers can "gracefully" shut down (moby/moby#25982 (comment)). This was verified by making a simple `main()` which implements the same code as in `ExampleNotify_allSignals` but in a `for` loop, building a `main.exe`, running that in a container, then doing `docker kill -sTERM` on said container. The program prints `Got signal: SIGTERM`, then exits after the aforementioned timeout, as expected. Behavior before this patch is that the program gets no notification (and thus no output) but still exits after the timeout. Fixes golang#7479
…NT as SIGTERM on Windows This matches the existing behavior of treating CTRL_C_EVENT, CTRL_BREAK_EVENT as a synthesized SIGINT event. See https://docs.microsoft.com/en-us/windows/console/handlerroutine for a good documentation source upstream to confirm these values. As for the usage of these events, the "Timeouts" section of that upstream documentation is important to note, especially the limited window in which to do any cleanup before the program will be forcibly killed (defaults typically 5s, but as low as 500ms, and in many cases configurable system-wide). These events are especially relevant for Windows containers, where these events (particularly `CTRL_SHUTDOWN_EVENT`) are one of the only ways containers can "gracefully" shut down (moby/moby#25982 (comment)). This was verified by making a simple `main()` which implements the same code as in `ExampleNotify_allSignals` but in a `for` loop, building a `main.exe`, running that in a container, then doing `docker kill -sTERM` on said container. The program prints `Got signal: SIGTERM`, then exits after the aforementioned timeout, as expected. Behavior before this patch is that the program gets no notification (and thus no output) but still exits after the timeout. Fixes golang#7479 Change-Id: I2af79421cd484a0fbb9467bb7ddb5f0e8bc3610e GitHub-Last-Rev: 9e05d63 GitHub-Pull-Request: golang#33311 Reviewed-on: https://go-review.googlesource.com/c/go/+/187739 Run-TryBot: Alex Brainman <alex.brainman@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
…NT as SIGTERM on Windows This matches the existing behavior of treating CTRL_C_EVENT, CTRL_BREAK_EVENT as a synthesized SIGINT event. See https://docs.microsoft.com/en-us/windows/console/handlerroutine for a good documentation source upstream to confirm these values. As for the usage of these events, the "Timeouts" section of that upstream documentation is important to note, especially the limited window in which to do any cleanup before the program will be forcibly killed (defaults typically 5s, but as low as 500ms, and in many cases configurable system-wide). These events are especially relevant for Windows containers, where these events (particularly `CTRL_SHUTDOWN_EVENT`) are one of the only ways containers can "gracefully" shut down (moby/moby#25982 (comment)). This was verified by making a simple `main()` which implements the same code as in `ExampleNotify_allSignals` but in a `for` loop, building a `main.exe`, running that in a container, then doing `docker kill -sTERM` on said container. The program prints `Got signal: SIGTERM`, then exits after the aforementioned timeout, as expected. Behavior before this patch is that the program gets no notification (and thus no output) but still exits after the timeout. Fixes golang#7479 Change-Id: I2af79421cd484a0fbb9467bb7ddb5f0e8bc3610e GitHub-Last-Rev: 9e05d63 GitHub-Pull-Request: golang#33311 Reviewed-on: https://go-review.googlesource.com/c/go/+/187739 Run-TryBot: Alex Brainman <alex.brainman@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
by anacrolix@google.com:
The text was updated successfully, but these errors were encountered: