diff --git a/temporal-service/build.sh b/temporal-service/build.sh index bdc2901c9d59..13baa5382f28 100755 --- a/temporal-service/build.sh +++ b/temporal-service/build.sh @@ -24,10 +24,10 @@ fi echo "Compiling Go binary..." if [ -n "${GOOS:-}" ] && [ -n "${GOARCH:-}" ]; then echo "Cross-compiling for ${GOOS}/${GOARCH}..." - GOOS="${GOOS}" GOARCH="${GOARCH}" go build -o "${BINARY_NAME}" . + GOOS="${GOOS}" GOARCH="${GOARCH}" go build -buildvcs=false -o "${BINARY_NAME}" . else echo "Building for current platform..." - go build -o "${BINARY_NAME}" . + go build -buildvcs=false -o "${BINARY_NAME}" . fi # Make it executable (skip on Windows as it's not needed) diff --git a/temporal-service/goose_workflow.go b/temporal-service/goose_workflow.go index 581610e1a2ad..637547ec8930 100644 --- a/temporal-service/goose_workflow.go +++ b/temporal-service/goose_workflow.go @@ -11,7 +11,6 @@ import ( "path/filepath" "runtime" "strings" - "syscall" "time" "go.temporal.io/sdk/activity" @@ -158,9 +157,7 @@ func executeBackgroundJobWithCancellation(ctx context.Context, jobID, recipePath ) // Set up process group for proper cleanup - cmd.SysProcAttr = &syscall.SysProcAttr{ - Setpgid: true, // Create new process group - } + configureSysProcAttr(cmd) // Set up environment cmd.Env = append(os.Environ(), @@ -278,9 +275,7 @@ func executeForegroundJobCLIWithCancellation(ctx context.Context, jobID string, ) // Set up process group for proper cleanup - cmd.SysProcAttr = &syscall.SysProcAttr{ - Setpgid: true, // Create new process group - } + configureSysProcAttr(cmd) // Set up environment cmd.Env = append(os.Environ(), diff --git a/temporal-service/main.go b/temporal-service/main.go index 22b92747cc25..b05942e5ed32 100644 --- a/temporal-service/main.go +++ b/temporal-service/main.go @@ -253,10 +253,7 @@ func ensureTemporalServerRunning(ports *PortConfig) error { cmd := exec.Command(temporalCmd, args...) // Properly detach the process so it survives when the parent exits - cmd.SysProcAttr = &syscall.SysProcAttr{ - Setpgid: true, // Create new process group - Pgid: 0, // Use process ID as group ID - } + configureSysProcAttr(cmd) // Redirect stdin/stdout/stderr to avoid hanging cmd.Stdin = nil diff --git a/temporal-service/process_manager.go b/temporal-service/process_manager.go index 7245c57a56ca..23af4e1e26e8 100644 --- a/temporal-service/process_manager.go +++ b/temporal-service/process_manager.go @@ -131,26 +131,20 @@ func killProcessGroup(process *os.Process) error { switch runtime.GOOS { case "windows": // On Windows, kill the process tree - cmd := exec.Command("taskkill", "/F", "/T", "/PID", fmt.Sprintf("%d", pid)) - if err := cmd.Run(); err != nil { - log.Printf("Failed to kill Windows process tree for PID %d: %v", pid, err) - return err - } - log.Printf("Successfully killed Windows process tree for PID %d", pid) - return nil + return killProcessGroupByPID(pid, 0) // signal parameter not used on Windows default: // On Unix-like systems, kill the process group more aggressively log.Printf("Killing Unix process group for PID %d", pid) // First, try to kill the entire process group with SIGTERM - if err := syscall.Kill(-pid, syscall.SIGTERM); err != nil { + if err := killProcessGroupByPID(pid, syscall.SIGTERM); err != nil { log.Printf("Failed to send SIGTERM to process group -%d: %v", pid, err) } else { log.Printf("Sent SIGTERM to process group -%d", pid) } // Also try to kill the main process directly - if err := syscall.Kill(pid, syscall.SIGTERM); err != nil { + if err := killProcessByPID(pid, syscall.SIGTERM); err != nil { log.Printf("Failed to send SIGTERM to process %d: %v", pid, err) } else { log.Printf("Sent SIGTERM to process %d", pid) @@ -160,14 +154,14 @@ func killProcessGroup(process *os.Process) error { time.Sleep(1 * time.Second) // Force kill the process group with SIGKILL - if err := syscall.Kill(-pid, syscall.SIGKILL); err != nil { + if err := killProcessGroupByPID(pid, syscall.SIGKILL); err != nil { log.Printf("Failed to send SIGKILL to process group -%d: %v", pid, err) } else { log.Printf("Sent SIGKILL to process group -%d", pid) } // Force kill the main process with SIGKILL - if err := syscall.Kill(pid, syscall.SIGKILL); err != nil { + if err := killProcessByPID(pid, syscall.SIGKILL); err != nil { log.Printf("Failed to send SIGKILL to process %d: %v", pid, err) } else { log.Printf("Sent SIGKILL to process %d", pid) @@ -229,7 +223,7 @@ func FindAndKillProcessesByPattern(jobID string) int { log.Printf("Found process %d matching pattern '%s' for job %s", pid, pattern, jobID) // Kill the process - if err := syscall.Kill(pid, syscall.SIGTERM); err != nil { + if err := killProcessByPID(pid, syscall.SIGTERM); err != nil { log.Printf("Failed to send SIGTERM to PID %d: %v", pid, err) } else { log.Printf("Sent SIGTERM to PID %d", pid) @@ -238,7 +232,7 @@ func FindAndKillProcessesByPattern(jobID string) int { // Wait a moment then force kill time.Sleep(500 * time.Millisecond) - if err := syscall.Kill(pid, syscall.SIGKILL); err != nil { + if err := killProcessByPID(pid, syscall.SIGKILL); err != nil { log.Printf("Failed to send SIGKILL to PID %d: %v", pid, err) } else { log.Printf("Sent SIGKILL to PID %d", pid) diff --git a/temporal-service/syscall_unix.go b/temporal-service/syscall_unix.go new file mode 100644 index 000000000000..bc57e3644136 --- /dev/null +++ b/temporal-service/syscall_unix.go @@ -0,0 +1,27 @@ +//go:build !windows +// +build !windows + +package main + +import ( + "os/exec" + "syscall" +) + +// configureSysProcAttr configures the SysProcAttr for Unix-like systems +func configureSysProcAttr(cmd *exec.Cmd) { + cmd.SysProcAttr = &syscall.SysProcAttr{ + Setpgid: true, // Create new process group + Pgid: 0, // Use process ID as group ID + } +} + +// killProcessByPID kills a process using Unix syscalls +func killProcessByPID(pid int, signal syscall.Signal) error { + return syscall.Kill(pid, signal) +} + +// killProcessGroupByPID kills a process group using Unix syscalls +func killProcessGroupByPID(pid int, signal syscall.Signal) error { + return syscall.Kill(-pid, signal) +} diff --git a/temporal-service/syscall_windows.go b/temporal-service/syscall_windows.go new file mode 100644 index 000000000000..ceae7dc85bc7 --- /dev/null +++ b/temporal-service/syscall_windows.go @@ -0,0 +1,32 @@ +//go:build windows +// +build windows + +package main + +import ( + "fmt" + "os/exec" + "syscall" +) + +// configureSysProcAttr configures the SysProcAttr for Windows +func configureSysProcAttr(cmd *exec.Cmd) { + // Windows doesn't support Setpgid/Pgid, so we use different approach + cmd.SysProcAttr = &syscall.SysProcAttr{ + CreationFlags: syscall.CREATE_NEW_PROCESS_GROUP, + } +} + +// killProcessByPID kills a process on Windows +func killProcessByPID(pid int, signal syscall.Signal) error { + // On Windows, we use taskkill command instead of syscall.Kill + cmd := exec.Command("taskkill", "/F", "/PID", fmt.Sprintf("%d", pid)) + return cmd.Run() +} + +// killProcessGroupByPID kills a process group on Windows +func killProcessGroupByPID(pid int, signal syscall.Signal) error { + // On Windows, kill the process tree + cmd := exec.Command("taskkill", "/F", "/T", "/PID", fmt.Sprintf("%d", pid)) + return cmd.Run() +} diff --git a/temporal-service/temporal-service b/temporal-service/temporal-service index 199d8f530029..5c520e23fece 100755 Binary files a/temporal-service/temporal-service and b/temporal-service/temporal-service differ