Skip to content

os/exec: Unable to kill a command on macOS? #27440

Closed
@andreynering

Description

@andreynering

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

go version go1.11 darwin/amd64

Does this issue reproduce with the latest release?

Yes

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

GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/andrey/Library/Caches/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/andrey/code/andrey/GOPATH"
GOPROXY=""
GORACE=""
GOROOT="/usr/local/Cellar/go/1.11/libexec"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.11/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/27/jbd81kh91cn15gq7sbm7xy580000gp/T/go-build184649496=/tmp/go-build -gno-record-gcc-switches -fno-common"

Reproduce

I think this is specific to macOS. Although I haven't tried the exact script below on another OS, I'm sure I ran similar scripts on Windows and Linux before and it worked fine

Given any long running executable:

package main

import (
	"fmt"
	"net/http"
)

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Hello, World!")
	})
	panic(http.ListenAndServe(":8080", nil))
}

Suppose we want to run the program above, but kill it after 5 seconds:

package main

import (
	"context"
	"fmt"
	"os/exec"
	"time"
)

func main() {
	ctx, cancel := context.WithCancel(context.Background())

	go func() {
		time.Sleep(5 * time.Second)
		fmt.Println("Trying to terminate server.go")
		cancel()
	}()

	fmt.Println("Starting command")
	if err := exec.CommandContext(ctx, "go", "run", "server.go").Run(); err != nil {
		panic(err)
	}
	fmt.Println("Terminating command")
}

The script above exits with a panic, but the server keeps running in background

I also tried to kill the process directly, but got the same result:

package main

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

func main() {
	cmd := exec.Command("go", "run", "./cmd/server/server.go")

	go func() {
		time.Sleep(5 * time.Second)
		fmt.Println("Trying to terminate server.go")
		cmd.Process.Signal(os.Kill)
	}()

	fmt.Println("Starting command")
	if err := cmd.Run(); err != nil {
		panic(err)
	}
	fmt.Println("Terminating command")
}

The interesting fact is that if I press Control+C before those 5 seconds then the server is killed without any problem

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeWaitingForInfoIssue is not actionable because of missing required information, which needs to be provided.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions