Skip to content

Commit d5e06bb

Browse files
committed
added unit test for lock file absense upon signaling the process group
Signed-off-by: reggie-k <regina.voloshin@codefresh.io>
1 parent 54dafb2 commit d5e06bb

File tree

1 file changed

+50
-0
lines changed

1 file changed

+50
-0
lines changed

util/exec/exec_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package exec
22

33
import (
4+
"os"
45
"os/exec"
6+
"path/filepath"
57
"regexp"
68
"syscall"
79
"testing"
@@ -215,3 +217,51 @@ func TestRunCaptureStderr(t *testing.T) {
215217
assert.Equal(t, "hello world\nmy-error", output)
216218
assert.NoError(t, err)
217219
}
220+
221+
// This test demonstrates that when a process group is signaled, all child processes are also terminated and file locks released.
222+
func TestProcessGroupSignalRemovesChildLock(t *testing.T) {
223+
hook := test.NewGlobal()
224+
log.SetLevel(log.DebugLevel)
225+
defer log.SetLevel(log.InfoLevel)
226+
227+
dir := t.TempDir()
228+
lockFile := filepath.Join(dir, "lockfile")
229+
childScript := filepath.Join(dir, "child.sh")
230+
parentScript := filepath.Join(dir, "parent.sh")
231+
232+
// Child: create lock file; on SIGTERM remove it and exit
233+
child := "#!/bin/sh\n" +
234+
"trap 'rm -f lockfile; exit 0' TERM\n" +
235+
"touch lockfile\n" +
236+
"sleep 100\n"
237+
require.NoError(t, os.WriteFile(childScript, []byte(child), 0o755))
238+
239+
// Parent: start child in background and sleep
240+
parent := "#!/bin/sh\n" +
241+
"./child.sh &\n" +
242+
"sleep 100\n"
243+
require.NoError(t, os.WriteFile(parentScript, []byte(parent), 0o755))
244+
245+
// Run parent with a short timeout; our implementation signals the process group
246+
opts := CmdOpts{
247+
Timeout: 500 * time.Millisecond,
248+
FatalTimeout: 500 * time.Millisecond,
249+
TimeoutBehavior: TimeoutBehavior{
250+
Signal: syscall.SIGTERM,
251+
ShouldWait: true,
252+
},
253+
}
254+
_, err := RunCommand("sh", opts, "-c", "cd "+dir+" && ./parent.sh")
255+
require.Error(t, err)
256+
257+
// Give a bit of time for traps to run and for the process tree to settle
258+
time.Sleep(200 * time.Millisecond)
259+
260+
// Because the process group was signaled, the child should have removed the lock
261+
_, statErr := os.Stat(lockFile)
262+
require.Error(t, statErr, "expected lock file to be removed when process group is signaled")
263+
assert.True(t, os.IsNotExist(statErr))
264+
265+
// basic sanity: logs produced
266+
require.GreaterOrEqual(t, len(hook.Entries), 1)
267+
}

0 commit comments

Comments
 (0)