Skip to content

os/signal: Notify doesn't catch signals when connecting os.Stdin to a subcommand #20159

@mbertschler

Description

@mbertschler

In some cases node Docker containers do not exit when you press ^C. I am writing a tool that starts these Docker containers, and want to catch the ^C and kill the program manually. The problem is just that once I connect the subcommands stdin with cmd.Stdin = os.Stdin, I do not get notified of ^C anymore.

I tried to reproduce the Docker behavior with a small Go program by catching signals and ignoring them, but that attempt was unsuccessful. This is why the reproducer is using Docker.

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

go version go1.8.1 darwin/amd64

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/mbertschler/go:/Users/mbertschler/wcd/go"
GORACE=""
GOROOT="/usr/local/Cellar/go/1.8.1/libexec"
GOTOOLDIR="/usr/local/Cellar/go/1.8.1/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/d0/zv0zzgf90r9bds00x6rm_qbr0000gn/T/go-build584631438=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"
PKG_CONFIG="pkg-config"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"

What did you do?

https://play.golang.org/p/GQ1YHd2Af-

package main

import (
	"fmt"
	"os"
	"os/exec"
	"os/signal"
)

func main() {
	ForceQuitter()
	Run("docker", "run", "--rm", "-it", "node:latest")
}

func ForceQuitter() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		<-c
		fmt.Println("[SIGINT force quit]")
		os.Exit(0)
	}()
}

func Run(name string, args ...string) error {
	cmd := exec.Command(name, args...)
	cmd.Stderr = os.Stderr
	cmd.Stdout = os.Stdout
	cmd.Stdin = os.Stdin
	return cmd.Run()
}

What did you expect to see?

$ signalkiller
> [SIGINT force quit]

What did you see instead?

To exit the node prompt you have to press ^C twice, but with this code it should exit immediately after the first one.

$ signalkiller
> 
(To exit, press ^C again or type .exit)
> 

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions