使用Git Bash/MINGW64和Go在Windows上捕获CTRL-C

ale*_*lex 11 bash mingw go git-bash

我想在用户点击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
  }
}
Run Code Online (Sandbox Code Playgroud)

在Windows上,当我使用Windows命令行时,这可以工作,但我希望它也适用于MINGW64/Git Bash.

我发现在/sf/answers/2238248981/上添加了

trap '' SIGINT
Run Code Online (Sandbox Code Playgroud)

到〜/ .bashrc捕获SIGINT信号并阻止bash终止我的程序.

这适用于MINGW32和bash版本

$ bash --version
GNU bash, version 3.1.20(4)-release (i686-pc-msys)
Copyright (C) 2005 Free Software Foundation, Inc.
Run Code Online (Sandbox Code Playgroud)

但它无法在MINGW64,bash版本上运行

$ bash --version
GNU bash, version 4.3.42(5)-release (x86_64-pc-msys)
Copyright (C) 2013 Free Software Foundation, Inc.
[...]
Run Code Online (Sandbox Code Playgroud)

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...")
    }
}
Run Code Online (Sandbox Code Playgroud)

MINGW32的输出(在〜/ .bashrc中使用陷阱''SIGINT):

$ ./sigint.exe
Working...
Working...
Working...
Interrupt received - calling cleanup()...
Cleaning up...
Working...
Working...
Cleaning up...
Working...
Cleaning up...
Working...
Working...
Quitting...
Run Code Online (Sandbox Code Playgroud)

cleanup()代码被执行.

MINGW64的输出(在〜/ .bashrc中也有陷阱''SIGINT):

$ ./sigint.exe
Working...
Working...
Working...
Working...
Run Code Online (Sandbox Code Playgroud)

cleanup()没有被执行.:-(

Phi*_*l K 5

用于winpty在Windows的Git Bash中正确捕获信号。它与安装捆绑在一起,因此您所需要做的就是:

$ winpty ./my-program.exe
Run Code Online (Sandbox Code Playgroud)