Created
February 4, 2025 14:22
-
-
Save evbruno/e9fd31007ff373a28ca158ce846fa8dd to your computer and use it in GitHub Desktop.
go - handling processes (Gemini)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Gemini version of https://gist.github.com/evbruno/13ba9181b64eeb063079d8d1146125b4 | |
package main | |
import ( | |
"context" | |
"fmt" | |
"os" | |
"os/exec" | |
"os/signal" | |
"slices" | |
"sync" | |
"syscall" | |
"time" | |
) | |
type ProcessJob struct { | |
ID int | |
Err error | |
Cmd string | |
} | |
func main() { | |
ctx, cancel := context.WithCancel(context.Background()) | |
defer cancel() // Ensure all processes are terminated on exit | |
sigChan := make(chan os.Signal, 1) | |
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM) | |
processes := make(map[int]*exec.Cmd) // Store processes by PID | |
var wg sync.WaitGroup | |
fmt.Println("Hello, World!") | |
startProcess(ctx, &wg, processes, "bash", "-c", "sleep 10") | |
startProcess(ctx, &wg, processes, "bash", "-c", "sleep 15") | |
go func() { | |
wg.Wait() | |
cancel() // Signal completion of all processes | |
}() | |
for { | |
select { | |
case sig := <-sigChan: | |
fmt.Printf("\nSignal received: %v. Terminating all processes...\n", sig) | |
terminateAllProcesses(processes) | |
return // Exit gracefully after termination | |
case <-ctx.Done(): | |
fmt.Println("All processes finished or terminated.") | |
return | |
} | |
} | |
} | |
func startProcess(ctx context.Context, wg *sync.WaitGroup, processes map[int]*exec.Cmd, name string, args ...string) { | |
wg.Add(1) | |
go func() { | |
defer wg.Done() | |
cmd := exec.CommandContext(ctx, name, args...) | |
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} // Ensure process group is created | |
cmdStr := fmt.Sprintf("%s %s", name, args) | |
fmt.Println("Starting:", cmdStr) | |
err := cmd.Start() | |
if err != nil { | |
fmt.Println("Error starting:", err) | |
return | |
} | |
processes[cmd.Process.Pid] = cmd // Store the command | |
fmt.Println("Started PID:", cmd.Process.Pid, cmdStr) | |
err = cmd.Wait() | |
if err != nil { | |
fmt.Println("Error waiting:", err) | |
} else { | |
fmt.Println("Finished PID:", cmd.Process.Pid, cmdStr) | |
} | |
delete(processes, cmd.Process.Pid) // Remove from the map when done | |
}() | |
} | |
func terminateAllProcesses(processes map[int]*exec.Cmd) { | |
for pid, cmd := range processes { | |
fmt.Printf("Stopping process (PID: %d): %v\n", pid, cmd.Args) | |
if cmd.Process != nil { | |
_ = syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL) // Kill entire process group | |
} | |
} | |
time.Sleep(1 * time.Second) // Allow time for processes to terminate | |
fmt.Println("All processes terminated.") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment