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:
authorPatrick Steinhardt <psteinhardt@gitlab.com>2022-01-11 13:54:37 +0300
committerPatrick Steinhardt <psteinhardt@gitlab.com>2022-01-14 17:25:03 +0300
commit532aec4b5020ef887bf899e984071a4c2443d283 (patch)
tree6db468874b2e1588ffc0869de7585d15a7e94fb1 /cmd/gitaly-wrapper
parent8cab4f8b7423dccc64211265d7d55a1028f86af1 (diff)
cmd/gitaly-wrapper: Add tests to check for process liveliness
When trying to adopt a process as pointed to by the PID file we have to test whether the PID exists at all anymore. Add tests to verify it works as expected. While at it, rename the function to `isProcessAlive()` to clarify what the function does.
Diffstat (limited to 'cmd/gitaly-wrapper')
-rw-r--r--cmd/gitaly-wrapper/main.go6
-rw-r--r--cmd/gitaly-wrapper/main_test.go49
2 files changed, 52 insertions, 3 deletions
diff --git a/cmd/gitaly-wrapper/main.go b/cmd/gitaly-wrapper/main.go
index 89b5be44d..8634c9d83 100644
--- a/cmd/gitaly-wrapper/main.go
+++ b/cmd/gitaly-wrapper/main.go
@@ -72,7 +72,7 @@ func main() {
forwardSignals(process, logger)
// wait
- for isAlive(process) {
+ for isProcessAlive(process) {
time.Sleep(1 * time.Second)
}
@@ -96,7 +96,7 @@ func findProcess(pidFilePath string) (*os.Process, error) {
return nil, err
}
- if isAlive(process) {
+ if isProcessAlive(process) {
return process, nil
}
@@ -156,7 +156,7 @@ func readPIDFile(pidFilePath string) (int, error) {
return strconv.Atoi(string(data))
}
-func isAlive(p *os.Process) bool {
+func isProcessAlive(p *os.Process) bool {
// After p exits, and after it gets reaped, this p.Signal will fail. It is crucial that p gets reaped.
// If p was spawned by the current process, it will get reaped from a goroutine that does cmd.Wait().
// If p was spawned by someone else we rely on them to reap it, or on p to become an orphan.
diff --git a/cmd/gitaly-wrapper/main_test.go b/cmd/gitaly-wrapper/main_test.go
index 0f053cb8f..19a20f4a1 100644
--- a/cmd/gitaly-wrapper/main_test.go
+++ b/cmd/gitaly-wrapper/main_test.go
@@ -204,3 +204,52 @@ func TestIsExpectedProcess(t *testing.T) {
require.False(t, isExpectedProcess(cmd.Process, "does not match"))
require.True(t, isExpectedProcess(cmd.Process, "bash"))
}
+
+func TestIsProcessAlive(t *testing.T) {
+ ctx, cancel := testhelper.Context()
+ defer cancel()
+
+ t.Run("nonexistent process", func(t *testing.T) {
+ // And now let's check with a nonexistent process. FindProcess never returns an
+ // error on Unix systems even if the process doesn't exist, so this is fine.
+ process, err := os.FindProcess(77777777)
+ require.NoError(t, err)
+ require.False(t, isProcessAlive(process))
+ })
+
+ t.Run("existing process", func(t *testing.T) {
+ executable := testhelper.WriteExecutable(t, filepath.Join(testhelper.TempDir(t), "noop"), []byte(
+ `#!/usr/bin/env bash
+ echo ready
+ read wait_until_killed
+ `))
+
+ cmd := exec.CommandContext(ctx, executable)
+ stdout, err := cmd.StdoutPipe()
+ require.NoError(t, err)
+ _, err = cmd.StdinPipe()
+ require.NoError(t, err)
+
+ require.NoError(t, cmd.Start())
+
+ // Wait for the process to be ready such that we know it's started up successfully
+ // and is executing the bash shell.
+ _, err = stdout.Read(make([]byte, 10))
+ require.NoError(t, err)
+
+ t.Run("running", func(t *testing.T) {
+ require.True(t, isProcessAlive(cmd.Process))
+ })
+
+ t.Run("zombie", func(t *testing.T) {
+ // The process will be considered alive as long as it hasn't been reaped yet.
+ require.NoError(t, cmd.Process.Kill())
+ require.True(t, isProcessAlive(cmd.Process))
+ })
+
+ t.Run("reaped", func(t *testing.T) {
+ require.Error(t, cmd.Wait())
+ require.False(t, isProcessAlive(cmd.Process))
+ })
+ })
+}