Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Newdigate <andrew@troupe.co>2017-05-09 08:14:00 +0300
committerAndrew Newdigate <andrew@troupe.co>2017-05-09 08:14:00 +0300
commit55a625bfb88e35971014dbdd1c48528e729fc553 (patch)
treee0040906aeb6d5d1b43bb9b3aefdac971f20773a
parent4583708801b7b69f820c76041a44200c8935d8f0 (diff)
Use process groups and kill the entire group on context cancelexperimental/context
-rw-r--r--internal/helper/command.go52
-rw-r--r--internal/helper/command_wrapper_go1.6.go44
-rw-r--r--internal/helper/command_wrapper_go17.go14
3 files changed, 47 insertions, 63 deletions
diff --git a/internal/helper/command.go b/internal/helper/command.go
index 5b9288757..fd10c5039 100644
--- a/internal/helper/command.go
+++ b/internal/helper/command.go
@@ -3,6 +3,7 @@ package helper
import (
"fmt"
"io"
+ "log"
"os"
"os/exec"
"syscall"
@@ -70,6 +71,15 @@ func NewCommand(cmd *exec.Cmd, stdin io.Reader, stdout io.Writer, env ...string)
return command, nil
}
+func cleanUpProcessGroupNoWait(cmd *exec.Cmd) {
+ process := cmd.Process
+ if process != nil && process.Pid > 0 {
+ // Send SIGTERM to the process group of cmd
+ syscall.Kill(-process.Pid, syscall.SIGTERM)
+ }
+
+}
+
// CleanUpProcessGroup will send a SIGTERM signal to the process group
// belonging to the `cmd` process
func CleanUpProcessGroup(cmd *exec.Cmd) {
@@ -77,11 +87,7 @@ func CleanUpProcessGroup(cmd *exec.Cmd) {
return
}
- process := cmd.Process
- if process != nil && process.Pid > 0 {
- // Send SIGTERM to the process group of cmd
- syscall.Kill(-process.Pid, syscall.SIGTERM)
- }
+ cleanUpProcessGroupNoWait(cmd)
// reap our child process
cmd.Wait()
@@ -101,3 +107,39 @@ func ExitStatus(err error) (int, bool) {
return waitStatus.ExitStatus(), true
}
+
+// CommandWrapper ensures that the command is executed within a context,
+// and ensures that the process group is terminated with the
+func CommandWrapper(ctx context.Context, name string, arg ...string) *exec.Cmd {
+ command := exec.Command(name, arg...)
+
+ if ctx != nil {
+ // Create a channel to listen to the command completion
+ done := make(chan error, 1)
+ go func() {
+ done <- command.Wait()
+ }()
+
+ // Wait for the process to shutdown or the
+ // context to be complete
+ go func() {
+ select {
+ case <-ctx.Done():
+ log.Printf("Context done, killing process")
+ cleanUpProcessGroupNoWait(command)
+
+ case err := <-done:
+ if err != nil {
+ log.Printf("process done with error = %v", err)
+ } else {
+ log.Print("process done gracefully without error")
+ }
+ cleanUpProcessGroupNoWait(command)
+
+ }
+
+ }()
+ }
+
+ return command
+}
diff --git a/internal/helper/command_wrapper_go1.6.go b/internal/helper/command_wrapper_go1.6.go
deleted file mode 100644
index c063a9a37..000000000
--- a/internal/helper/command_wrapper_go1.6.go
+++ /dev/null
@@ -1,44 +0,0 @@
-// +build !go1.7
-
-package helper
-
-import (
- "log"
- "os/exec"
-
- "golang.org/x/net/context"
-)
-
-// CommandWrapper handles context until we compile using Go 1.7
-func CommandWrapper(ctx context.Context, name string, arg ...string) *exec.Cmd {
- command := exec.Command(name, arg...)
-
- if ctx != nil {
- // Create a channel to listen to the command completion
- done := make(chan error, 1)
- go func() {
- done <- command.Wait()
- }()
-
- // Wait for the process to shutdown or the
- // context to be complete
- go func() {
- select {
- case <-ctx.Done():
- log.Printf("Context done, killing process")
- command.Process.Kill()
-
- case err := <-done:
- if err != nil {
- log.Printf("process done with error = %v", err)
- } else {
- log.Print("process done gracefully without error")
- }
-
- }
-
- }()
- }
-
- return command
-}
diff --git a/internal/helper/command_wrapper_go17.go b/internal/helper/command_wrapper_go17.go
deleted file mode 100644
index c381331b5..000000000
--- a/internal/helper/command_wrapper_go17.go
+++ /dev/null
@@ -1,14 +0,0 @@
-//+build go1.7
-
-package helper
-
-import (
- "os/exec"
-
- "golang.org/x/net/context"
-)
-
-// CommandWrapper handles context until we compile using Go 1.7
-func CommandWrapper(ctx context.Context, name string, arg ...string) *exec.Cmd {
- return exec.CommandContext(ctx, name, arg...)
-}