package main import ( "context" "os" "os/exec" "runtime" "sync/atomic" ) // startedFrom is the path this process's executable had when it started: what a verb's command line // is named in a process listing, and what is run where the image cannot be named otherwise. var startedFrom, _ = os.Executable() // ownImage is how a process names the executable it is running, as long as it runs, wherever the file // has gone since. On Linux the kernel keeps it: /proc/self/exe is the running image itself, not a path, // so it is valid after the file is renamed into a directory this process may not enter, or deleted — // which is what the node-engine's witness does to a build it replaces (novox/hq issue 289). Read in the // child, it names the child's image, which until the exec is this process's. // // os.Executable reads the same link and returns the path it points at *now*: correct at start and // wrong the moment the file moves, which is the fault. A variable so a test can name another. var ownImage = func() string { if runtime.GOOS == "linux" { if _, err := os.Stat("/proc/self/exe"); err == nil { return "/proc/self/exe" } } return startedFrom } // selfCommand is this binary run with a command line: the image this process runs, named in a process // listing as the path it started from. func selfCommand(ctx context.Context, argv []string) *exec.Cmd { cmd := exec.CommandContext(ctx, ownImage(), argv...) if startedFrom != "" { cmd.Args[0] = startedFrom } return cmd } // handingOver is set when the serving controller begins to stop — a signal from its supervisor, a lease // lost. From then a verb that would run a command is refused as a handover rather than started and // killed with this process: the caller asks again, and the controller after this one answers // (novox/hq issue 289). var handingOver atomic.Bool