reExec runs the freshly-installed binary. Windows has no execve, so instead of the Unix same-PID swap we spawn it as a child sharing our stdio, wait, and forward its exit code: one continuous session despite two brief PIDs. signal.Ignore(os.Interrupt) is load-bearing: otherwise the parent's default
(exe string, args []string, env []string)
| 18 | // on the same console, interleaving the shell prompt with its TUI. Ignoring |
| 19 | // it funnels all console Ctrl+C to the child, which has its own handler. |
| 20 | func reExec(exe string, args []string, env []string) error { |
| 21 | signal.Ignore(os.Interrupt) |
| 22 | cmd := exec.Command(exe, args[1:]...) |
| 23 | cmd.Stdin = os.Stdin |
| 24 | cmd.Stdout = os.Stdout |
| 25 | cmd.Stderr = os.Stderr |
| 26 | cmd.Env = env |
| 27 | if err := cmd.Run(); err != nil { |
| 28 | // Nonzero child exit is success here: the new binary ran, so |
| 29 | // just propagate its code to the shell. Anything else (spawn |
| 30 | // failure, missing binary) is a real error the caller surfaces, |
| 31 | // falling through to the old in memory binary. |
| 32 | if ee, ok := err.(*exec.ExitError); ok { |
| 33 | os.Exit(ee.ExitCode()) |
| 34 | } |
| 35 | return err |
| 36 | } |
| 37 | os.Exit(0) |
| 38 | return nil |
| 39 | } |
nothing calls this directly
no outgoing calls
no test coverage detected