【发布时间】:2016-12-13 22:54:29
【问题描述】:
当用户按下 CTRL-C 时,我想在退出之前运行特定代码。代码在 Go 中,我想使用 Git Bash / MINGW64 在 Windows 上运行它。使用 Go,我愿意
interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
// some goroutines get started here
// ...
for {
select {
case <-interrupt:
// code which shall be run on CTRL-C
}
}
在 Windows 上,这在我使用 Windows 命令行时有效,但我希望它也能在 MINGW64/Git Bash 上工作。
我在https://stackoverflow.com/a/31974985/1370397 上发现添加
trap '' SIGINT
to ~/.bashrc 捕获 SIGINT 信号并防止 bash 终止我的程序。
这适用于我在带有 bash 版本的 MINGW32 上
$ bash --version
GNU bash, version 3.1.20(4)-release (i686-pc-msys)
Copyright (C) 2005 Free Software Foundation, Inc.
但它无法在 MINGW64,bash 版本上运行
$ bash --version
GNU bash, version 4.3.42(5)-release (x86_64-pc-msys)
Copyright (C) 2013 Free Software Foundation, Inc.
[...]
MINGW64 或新 (git) bash 版本有什么不同?
为了更容易测试,下面是一个查看行为差异的最小示例:
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
"time"
)
func cleanup(){
for i:=0; i<3; i++ {
fmt.Println("Cleaning up...")
time.Sleep(500*time.Millisecond)
}
}
func work() {
for {
fmt.Println("Working...")
time.Sleep(300*time.Millisecond)
}
}
func main() {
interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
go work()
for {
select {
case <-interrupt:
fmt.Println("Interrupt received - calling cleanup()...")
cleanup()
fmt.Println("Quitting...")
return
}
fmt.Println("Waiting...")
}
}
来自 MINGW32 的输出(在 ~/.bashrc 中带有陷阱 '' SIGINT):
$ ./sigint.exe
Working...
Working...
Working...
Interrupt received - calling cleanup()...
Cleaning up...
Working...
Working...
Cleaning up...
Working...
Cleaning up...
Working...
Working...
Quitting...
cleanup() 代码被执行。
来自 MINGW64 的输出(在 ~/.bashrc 中也带有陷阱 '' SIGINT):
$ ./sigint.exe
Working...
Working...
Working...
Working...
cleanup() 没有被执行。 :-(
【问题讨论】:
-
这里似乎有人有类似的设置sourceforge.net/p/mingw-w64/bugs/561 可能值得跟进 Keynan Pratt。有人提到它可能是一个 GO 错误。但从你所说的可能它在 MINGW64 中。您或许应该在此处将指针添加回您的帖子。
-
不是 Go 的错误,实际上,如果你在 C 中尝试同样的方法也会发生。