Skip to content

Instantly share code, notes, and snippets.

@Nonlinearsound
Last active November 5, 2023 23:36
Show Gist options
  • Save Nonlinearsound/cf2064b5d0a42de9ef1ef64d79511fda to your computer and use it in GitHub Desktop.
Save Nonlinearsound/cf2064b5d0a42de9ef1ef64d79511fda to your computer and use it in GitHub Desktop.
Go: Execute a sub process and kill it from within the host application

Description

This example program creates a context using the context.WithCancel() method from the context package.

WithCancel creates the context while returning a cancel function that can be called to prematurely cancel/end the context.

exec.CommandContext(ctx, ".\\test.exe", "e") is exec.Command() but with creating a context around the creation and execution of the sub process. Using that context, the execution of the sub process can now be ended prematurely.

The text.exe is another compiled and linked Go program, that just loops forever, printing "ENDLESS.." to the console. As the example program calls cmd.Wait() it waits for the sub process to end, either by it ending by itself od because of being killed by another system process.

Without ending the context, the sub process and so our program would run forever..

We will now start a go-routine and inside of it sleep for two seconds and call the created cancel() method to kill the sub process.

As we can see, the main program ends right after that, so we successfully killed the sub process prematurely.

package main

import (
	"context"
	"fmt"
	"os/exec"
	"time"
)

func main() {

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	// Start the process in the background
	cmd := exec.CommandContext(ctx, ".\\test.exe", "e")
	err := cmd.Start()
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	fmt.Printf("Process started with PID: %d\n", cmd.Process.Pid)
	
	// by now, the test.exe sub process is running and I wrote test.exe to loop forever
	// and print out the string "ENDLESS.." to the console.

	// Start a co-routine that calls the cancel-Function after 2 Seconds
	// By that, the created sub process will be killed and the current program will end
	// as cmd.Wait() finishes
	go func() {
		time.Sleep(2 * time.Second)
		cancel()
	}()

	// Wait for the process to complete
	err = cmd.Wait()
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}
	fmt.Println("Process completed.")
}

The guest program, that loops forever (test.exe)

package main

import (
	"os"
	"time"
)

func main() {
	endless := os.Args[1]
	if endless == "e" {
		for {
			println("ENDLESS..")
			time.Sleep(5 * time.Second)
		}
	} else {
		println("TEST")
	}

}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment