Skip to content

Instantly share code, notes, and snippets.

@evbruno
Created February 4, 2025 14:21
Show Gist options
  • Save evbruno/13ba9181b64eeb063079d8d1146125b4 to your computer and use it in GitHub Desktop.
Save evbruno/13ba9181b64eeb063079d8d1146125b4 to your computer and use it in GitHub Desktop.
go - handling processes (v1)
# learning go day 3
package main
import (
"fmt"
"os"
"os/exec"
"os/signal"
"slices"
"syscall"
"time"
)
type ProcessJob struct {
id int
err error
cmd string
}
func main() {
// Channel to catch termination signals (e.g., CTRL+C)
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
// Channel to detect process failure or completion
doneChan := make(chan ProcessJob, 1)
startChan := make(chan int)
processes := make([]int, 0)
fmt.Println("Hello, World!")
go runn(doneChan, startChan, "bash", "-c", "sleep 10")
go runn(doneChan, startChan, "bash", "-c", "sleep 15")
for {
select {
case pid := <-startChan:
// Store the PID of the process
processes = append(processes, pid)
fmt.Println("Processes started:", processes)
fmt.Println("")
case job := <-doneChan:
// If any process crashes, stop all !?
if err := job.err; err != nil {
fmt.Printf("Process %d failed: %v\n", job.id, err)
} else {
fmt.Printf("Process %d completed: %v\n", job.id, job.cmd)
}
// remove the process from the list
pid_idx := slices.Index(processes, job.id)
processes = slices.Delete(processes, pid_idx, pid_idx+1)
fmt.Println("Processes:", processes)
fmt.Println("")
case t := <-sigChan:
// Handle CTRL+C
fmt.Printf("\nCTRL+C received! Terminating all processes... %v\n", t)
fmt.Println("Processes:", processes)
terminateAllPids(processes)
}
}
}
func runn(done chan ProcessJob, start chan int, name string, args ...string) {
action := fmt.Sprintf("%s %s", name, args)
for {
cmd := exec.Command(name, args...)
fmt.Println("Starting:", action)
err := cmd.Start()
if err != nil {
fmt.Println("Error Start:", err)
done <- ProcessJob{0, err, action}
continue
}
go func() { start <- cmd.Process.Pid }()
fmt.Println("await PID:", cmd.Process.Pid, "wait", action)
err = cmd.Wait()
if err != nil {
fmt.Println("Error Wait:", err)
done <- ProcessJob{cmd.Process.Pid, err, action}
continue
}
fmt.Println("done PID:", cmd.Process.Pid, action)
done <- ProcessJob{cmd.Process.Pid, nil, action}
}
}
// Terminate all running processes
func terminateAllPids(pids []int) {
for _, pid := range pids {
fmt.Printf("Stopping process (PID: %d)\n", pid)
_ = syscall.Kill(-pid, syscall.SIGKILL) // Kill entire process group
}
time.Sleep(1 * time.Second) // Allow time for processes to terminate
fmt.Println("All processes terminated.")
os.Exit(1)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment