Skip to content

Commit

Permalink
innermost child
Browse files Browse the repository at this point in the history
  • Loading branch information
tamird committed Oct 18, 2024
1 parent 897520f commit cbb8872
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 11 deletions.
2 changes: 1 addition & 1 deletion cargo-generate.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[template]
cargo_generate_version = ">=0.10.0"
ignore = [".github", "test.py"]
ignore = [".github", "main.go"]

[placeholders.program_type]
type = "string"
Expand Down
66 changes: 56 additions & 10 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import (
"os/exec"
"path/filepath"
"runtime"
"strconv"
"strings"
"syscall"
"time"
)

Expand Down Expand Up @@ -157,24 +157,19 @@ func run() error {
cmd.Env = cmdSpec.Env
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
fmt.Printf("%+v\n", cmdSpec)
fmt.Printf("%#v\n", cmdSpec)
if err := cmd.Run(); err != nil {
return fmt.Errorf("%+v failed: %w", cmdSpec, err)
return fmt.Errorf("%#v failed: %w", cmdSpec, err)
}
}

if runtime.GOOS == "linux" {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

cmd := exec.CommandContext(ctx, "cargo", "xtask", "run")
cmd := exec.CommandContext(ctx, "sh", "-c", "cargo xtask run")
cmd.Dir = projectDir
cmd.Stderr = os.Stderr
// Prevent the child process from being in our process group so that we can send it a SIGINT
// without sending one to ourselves.
cmd.SysProcAttr = &syscall.SysProcAttr{
Setpgid: true,
}

stdoutPipe, err := cmd.StdoutPipe()
if err != nil {
Expand All @@ -192,8 +187,17 @@ func run() error {
if _, err := fmt.Fprintln(os.Stdout, text); err != nil {
panic(err)
}

if strings.Contains(text, "Waiting for Ctrl-C") {
syscall.Kill(-cmd.Process.Pid, syscall.SIGINT)
for process, err := range children(cmd.Process) {
if err != nil {
return err
}
fmt.Printf("Sending SIGINT to child pid %d\n", process.Pid)
if err := process.Signal(os.Interrupt); err != nil {
return fmt.Errorf("failed to interrupt %d: %w", process, err)
}
}
}
}
if err := scanner.Err(); err != nil {
Expand All @@ -207,3 +211,45 @@ func run() error {

return nil
}

func children(process *os.Process) func(func(*os.Process, error) bool) {
return func(yield func(*os.Process, error) bool) {
if !yield(process, nil) {
return
}
taskPath := fmt.Sprintf("/proc/%d/task", process.Pid)
entries, err := os.ReadDir(taskPath)
if err != nil {
yield(nil, fmt.Errorf("failed to readdir %s: %w", taskPath, err))
return
}
for _, entry := range entries {
if !entry.IsDir() {
continue
}
childrenPath := fmt.Sprintf("%s/%s/children", taskPath, entry.Name())
childrenContent, err := os.ReadFile(childrenPath)
if err != nil {
yield(nil, fmt.Errorf("failed to read %s: %w", childrenPath, err))
return
}
for _, childField := range strings.Fields(string(childrenContent)) {
childPid, err := strconv.Atoi(childField)
if err != nil {
yield(nil, fmt.Errorf("failed to parse %s: %w", childField, err))
return
}
child, err := os.FindProcess(childPid)
if err != nil {
yield(nil, fmt.Errorf("failed to find process %d: %w", childPid, err))
return
}
for process, err := range children(child) {
if !yield(process, err) {
return
}
}
}
}
}
}

0 comments on commit cbb8872

Please sign in to comment.