Skip to content

Commit a5f07f7

Browse files
nervghalexey-igrychev
authored andcommitted
fix(host-cleanup): auto host cleanup doesn't work on linux
Signed-off-by: Alexandr Zaytsev <alexandr.zaytsev@flant.com>
1 parent 6b12c0d commit a5f07f7

File tree

4 files changed

+86
-34
lines changed

4 files changed

+86
-34
lines changed

Diff for: pkg/host_cleaning/host_cleanup.go

+2-34
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,12 @@ import (
44
"context"
55
"errors"
66
"fmt"
7-
"os"
8-
"os/exec"
9-
"strings"
107

118
"github.com/werf/logboek"
129
"github.com/werf/werf/v2/pkg/container_backend"
1310
"github.com/werf/werf/v2/pkg/git_repo/gitdata"
1411
"github.com/werf/werf/v2/pkg/tmp_manager"
12+
"github.com/werf/werf/v2/pkg/werf/exec"
1513
)
1614

1715
const (
@@ -86,37 +84,7 @@ func RunAutoHostCleanup(ctx context.Context, backend container_backend.Container
8684
args = append(args, "--backend-storage-path", *options.BackendStoragePath)
8785
}
8886

89-
executableName := os.Getenv("WERF_ORIGINAL_EXECUTABLE")
90-
if executableName == "" {
91-
executableName = os.Args[0]
92-
}
93-
94-
cmd := exec.Command(executableName, args...)
95-
96-
var env []string
97-
for _, spec := range os.Environ() {
98-
k := strings.SplitN(spec, "=", 2)[0]
99-
if k == "WERF_ENABLE_PROCESS_EXTERMINATOR" {
100-
continue
101-
}
102-
103-
env = append(env, spec)
104-
}
105-
env = append(env, "_WERF_BACKGROUND_MODE_ENABLED=1")
106-
107-
cmd.Env = env
108-
109-
if err := cmd.Start(); err != nil {
110-
logboek.Context(ctx).Warn().LogF("WARNING: unable to start background auto host cleanup process: %s\n", err)
111-
return nil
112-
}
113-
114-
if err := cmd.Process.Release(); err != nil {
115-
logboek.Context(ctx).Warn().LogF("WARNING: unable to detach background auto host cleanup process: %s\n", err)
116-
return nil
117-
}
118-
119-
return nil
87+
return exec.Detach(ctx, args)
12088
}
12189

12290
func RunHostCleanup(ctx context.Context, backend container_backend.ContainerBackend, options HostCleanupOptions) error {

Diff for: pkg/util/exec/unix.go

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//go:build linux || darwin
2+
3+
package exec
4+
5+
import (
6+
"os/exec"
7+
"syscall"
8+
9+
"github.com/werf/werf/v2/pkg/util/option"
10+
)
11+
12+
// MakeDetachable ensures command could start a detachable process.
13+
// Detachable process is a group leader process which has not controlling terminal.
14+
func MakeDetachable(cmd *exec.Cmd) *exec.Cmd {
15+
attr := option.PtrValueOrDefault(cmd.SysProcAttr, syscall.SysProcAttr{})
16+
17+
// Creates a new session if the calling process is not a process group leader and sets the process group ID.
18+
// Ensures the process has not controlling terminal.
19+
// Note. A process group leader is a process whose process group ID equals its PID.
20+
// https://man7.org/linux/man-pages/man2/setsid.2.html
21+
attr.Setsid = true
22+
23+
cmd.SysProcAttr = &attr
24+
25+
return cmd
26+
}

Diff for: pkg/util/exec/windows.go

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//go:build windows
2+
3+
package exec
4+
5+
import (
6+
"os/exec"
7+
)
8+
9+
// MakeDetachable ensures command could start detachable process.
10+
func MakeDetachable(cmd *exec.Cmd) *exec.Cmd {
11+
// We don't know right now there is or there is not the process detaching problem on Windows.
12+
// Moreover, syscall.SysProcAttr for windows has not "Setsid" (linux specific) field.
13+
// So we keep cross-platform compatibility do nothing.
14+
15+
return cmd
16+
}

Diff for: pkg/werf/exec/exec.go

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package exec
2+
3+
import (
4+
"context"
5+
"os"
6+
"os/exec"
7+
"strings"
8+
9+
"github.com/samber/lo"
10+
11+
"github.com/werf/logboek"
12+
exec2 "github.com/werf/werf/v2/pkg/util/exec"
13+
"github.com/werf/werf/v2/pkg/util/option"
14+
)
15+
16+
// Detach executes werf binary in new detached process.
17+
// The detached process will continue to work after termination of parent process.
18+
func Detach(ctx context.Context, args []string) error {
19+
name := option.ValueOrDefault(os.Getenv("WERF_ORIGINAL_EXECUTABLE"), os.Args[0])
20+
21+
env := append(os.Environ(), "_WERF_BACKGROUND_MODE_ENABLED=1")
22+
23+
env = lo.Filter(env, func(item string, _ int) bool {
24+
return !strings.HasPrefix(item, "WERF_ENABLE_PROCESS_EXTERMINATOR=")
25+
})
26+
27+
cmd := exec.Command(name, args...)
28+
cmd.Env = env
29+
30+
cmd = exec2.MakeDetachable(cmd)
31+
32+
if err := cmd.Start(); err != nil {
33+
logboek.Context(ctx).Warn().LogF("WARNING: unable to start background process: %s\n", err)
34+
return nil
35+
}
36+
37+
if err := cmd.Process.Release(); err != nil {
38+
logboek.Context(ctx).Warn().LogF("WARNING: unable to detach background process: %s\n", err)
39+
}
40+
41+
return nil
42+
}

0 commit comments

Comments
 (0)