mirror of
https://github.com/docker/compose.git
synced 2025-07-31 01:24:15 +02:00
Merge pull request #157 from docker/kill_child_process_on_cancel
Kill child process "docker-classic" on cancel
This commit is contained in:
commit
832651b1dc
2
Makefile
2
Makefile
@ -66,7 +66,7 @@ lint: ## run linter(s)
|
|||||||
--target lint
|
--target lint
|
||||||
|
|
||||||
classic-link: ## create docker-classic symlink if does not already exist
|
classic-link: ## create docker-classic symlink if does not already exist
|
||||||
ln -s /usr/local/bin/docker-classic /Applications/Docker.app/Contents/Resources/bin/docker
|
ln -s /Applications/Docker.app/Contents/Resources/bin/docker /usr/local/bin/docker-classic
|
||||||
|
|
||||||
help: ## Show help
|
help: ## Show help
|
||||||
@echo Please specify a build target. The choices are:
|
@echo Please specify a build target. The choices are:
|
||||||
|
@ -186,7 +186,7 @@ func execMoby(ctx context.Context) {
|
|||||||
// Only run original docker command if the current context is not
|
// Only run original docker command if the current context is not
|
||||||
// ours.
|
// ours.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmd := exec.Command("docker-classic", os.Args[1:]...)
|
cmd := exec.CommandContext(ctx, "docker-classic", os.Args[1:]...)
|
||||||
cmd.Stdin = os.Stdin
|
cmd.Stdin = os.Stdin
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
|
@ -29,17 +29,20 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gotest.tools/golden"
|
|
||||||
|
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
|
"gotest.tools/golden"
|
||||||
|
|
||||||
. "github.com/docker/api/tests/framework"
|
. "github.com/docker/api/tests/framework"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -79,6 +82,37 @@ func (s *E2eSuite) TestSetupError() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *E2eSuite) TestKillChildOnCancel() {
|
||||||
|
It("should kill docker-classic if parent command is cancelled", func() {
|
||||||
|
out := s.NewCommand("ps", "-x").ExecOrDie()
|
||||||
|
Expect(out).NotTo(ContainSubstring("docker-classic"))
|
||||||
|
|
||||||
|
dir := s.ConfigDir
|
||||||
|
Expect(ioutil.WriteFile(filepath.Join(dir, "Dockerfile"), []byte(`FROM alpine:3.10
|
||||||
|
RUN sleep 100`), 0644)).To(Succeed())
|
||||||
|
shutdown := make(chan time.Time)
|
||||||
|
errs := make(chan error)
|
||||||
|
ctx := s.NewDockerCommand("build", "--no-cache", "-t", "test-sleep-image", ".").WithinDirectory(dir).WithTimeout(shutdown)
|
||||||
|
go func() {
|
||||||
|
_, err := ctx.Exec()
|
||||||
|
errs <- err
|
||||||
|
}()
|
||||||
|
err := WaitFor(time.Second, 3*time.Second, errs, func() bool {
|
||||||
|
out := s.NewCommand("ps", "-x").ExecOrDie()
|
||||||
|
return strings.Contains(out, "docker-classic")
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
log.Println("Killing docker process")
|
||||||
|
|
||||||
|
close(shutdown)
|
||||||
|
err = WaitFor(time.Second, 4*time.Second, nil, func() bool {
|
||||||
|
out := s.NewCommand("ps", "-x").ExecOrDie()
|
||||||
|
return !strings.Contains(out, "docker-classic")
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (s *E2eSuite) TestLegacy() {
|
func (s *E2eSuite) TestLegacy() {
|
||||||
It("should list all legacy commands", func() {
|
It("should list all legacy commands", func() {
|
||||||
output := s.NewDockerCommand("--help").ExecOrDie()
|
output := s.NewDockerCommand("--help").ExecOrDie()
|
||||||
|
@ -33,6 +33,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/onsi/gomega"
|
"github.com/onsi/gomega"
|
||||||
@ -129,6 +130,29 @@ func (b CmdContext) Exec() (string, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//WaitFor waits for a condition to be true
|
||||||
|
func WaitFor(interval, duration time.Duration, abort <-chan error, condition func() bool) error {
|
||||||
|
ticker := time.NewTicker(interval)
|
||||||
|
defer ticker.Stop()
|
||||||
|
timeout := make(chan int)
|
||||||
|
go func() {
|
||||||
|
time.Sleep(duration)
|
||||||
|
close(timeout)
|
||||||
|
}()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case err := <-abort:
|
||||||
|
return err
|
||||||
|
case <-timeout:
|
||||||
|
return fmt.Errorf("timeout after %v", duration)
|
||||||
|
case <-ticker.C:
|
||||||
|
if condition() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Execute executes a command.
|
// Execute executes a command.
|
||||||
// The command cannot be re-used afterwards.
|
// The command cannot be re-used afterwards.
|
||||||
func Execute(cmd *exec.Cmd, timeout <-chan time.Time) (string, error) {
|
func Execute(cmd *exec.Cmd, timeout <-chan time.Time) (string, error) {
|
||||||
@ -152,7 +176,7 @@ func Execute(cmd *exec.Cmd, timeout <-chan time.Time) (string, error) {
|
|||||||
}
|
}
|
||||||
case <-timeout:
|
case <-timeout:
|
||||||
log.Debugf("%s %s timed-out", cmd.Path, strings.Join(cmd.Args[1:], " "))
|
log.Debugf("%s %s timed-out", cmd.Path, strings.Join(cmd.Args[1:], " "))
|
||||||
if err := cmd.Process.Kill(); err != nil {
|
if err := cmd.Process.Signal(syscall.SIGTERM); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return "", fmt.Errorf(
|
return "", fmt.Errorf(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user