Created
February 4, 2025 14:21
-
-
Save evbruno/13ba9181b64eeb063079d8d1146125b4 to your computer and use it in GitHub Desktop.
go - handling processes (v1)
This file contains 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
# 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