Skip to content
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/exec: shell command can't be killed when output redirected with cmd.exe #22381

Closed
math2001 opened this issue Oct 22, 2017 · 2 comments
Closed
Labels
FrozenDueToAge help wanted NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. OS-Windows
Milestone

Comments

@math2001
Copy link

When I run a shell command with cmd.exe and redirect either the stdout or the stderr, the command cannot be killed (it says that it has been killed once the command is done, but it keeps running).

Here's the code (try to comment out cmd.Stdout =... and cmd.Stderr =...):

package main

import "os/exec"
import "fmt"
import "time"
import "bytes"

func main() {
    cmd := exec.Command("cmd.exe", "/C", "sleep 2")
    var stdout bytes.Buffer
    var stderr bytes.Buffer

    cmd.Stdout = &stdout
    cmd.Stderr = &stderr

    start := time.Now()
    fmt.Println(cmd.Start())
    timer := time.AfterFunc(1 * time.Second, func () {
        fmt.Println("killed", cmd.Process.Kill())

    })
    fmt.Println(cmd.Wait())
    timer.Stop()
    fmt.Println(time.Since(start))
}

It outputs this:

<nil>
killed <nil>
exit status 1
2.0313611s

And without the redirects, the output is:

<nil>
killed <nil>
exit status 1
1.0205677s

System details

go version go1.9.1 windows/amd64
GOARCH="amd64"
GOBIN=""
GOEXE=".exe"
GOHOSTARCH="amd64"
GOHOSTOS="windows"
GOOS="windows"
GOPATH="C:\Users\Home\gopackages"
GORACE=""
GOROOT="C:\Go"
GOTOOLDIR="C:\Go\pkg\tool\windows_amd64"
GCCGO="gccgo"
CC="gcc"
GOGCCFLAGS="-m64 -mthreads -fmessage-length=0"
CXX="g++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOROOT/bin/go version: go version go1.9.1 windows/amd64
GOROOT/bin/go tool compile -V: compile version go1.9.1
@gbbr gbbr changed the title Shell command can't be killed when output redirected with cmd.exe os/exec: shell command can't be killed when output redirected with cmd.exe Oct 22, 2017
@ianlancetaylor ianlancetaylor added OS-Windows NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. labels Oct 23, 2017
@ianlancetaylor ianlancetaylor added this to the Go1.10 milestone Oct 23, 2017
@ianlancetaylor ianlancetaylor modified the milestones: Go1.10, Go1.11 Dec 6, 2017
@karkason
Copy link

karkason commented Feb 23, 2018

The issue here is how Windows Named Pipes react to handles inheritence.

When you invoke cmd /c "sleep 2" you launch a cmd.exe which in turn launches sleep.exe (by the way, that's not a native Windows exectuable - it's from a MinGW and the likes).

Cmd.Start launches an I/O loop copying data from an internally-managed os.Pipe to the stdout/stderr io.Writers (the writerDescriptor function adds it to the queue).
The Named Pipe handle created by os.Pipe is inherited by the sleep.exe. When calling Process.Kill the cmd.exe is in fact killed, but the child sleep.exe isn't, and because it still has the inherited pipe it keeps on running until it's done.

So if we want it to properly function we have a couple of options:

  • Add a method: Cmd.Kill which will make sure we are properly closing the Pipe handle on our side (which would render the Pipe unusable)
  • Add a way to register extra handles (or fds) to close when calling Process.Kill

@ianlancetaylor
Copy link
Contributor

See #23019 and the issues to which it refers. Closing as dup.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge help wanted NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. OS-Windows
Projects
None yet
Development

No branches or pull requests

4 participants