detectVersion probes the binary with a sequence of version flags, returning the first non-empty response. Each probe is bounded: the process is killed after versionProbeTimeout, and its pipes are forcibly closed after versionProbeWaitDelay so a hung grandchild can't deadlock the read. If a flag time
(bin string)
| 191 | // times out, the remaining flags are skipped — a binary that hangs on one |
| 192 | // version flag will hang on the others too. |
| 193 | func detectVersion(bin string) string { |
| 194 | for _, flag := range []string{"--version", "-v", "version"} { |
| 195 | ctx, cancel := context.WithTimeout(context.Background(), versionProbeTimeout) |
| 196 | cmd := exec.CommandContext(ctx, bin, flag) |
| 197 | cmd.WaitDelay = versionProbeWaitDelay |
| 198 | out, err := cmd.CombinedOutput() |
| 199 | timedOut := ctx.Err() != nil // deadline fired (cancel runs below) |
| 200 | cancel() |
| 201 | if err != nil { |
| 202 | if timedOut { |
| 203 | break |
| 204 | } |
| 205 | continue |
| 206 | } |
| 207 | s := strings.TrimSpace(string(out)) |
| 208 | if s == "" { |
| 209 | continue |
| 210 | } |
| 211 | // Take the last non-empty line. |
| 212 | lines := strings.Split(s, "\n") |
| 213 | for i := len(lines) - 1; i >= 0; i-- { |
| 214 | line := strings.TrimSpace(lines[i]) |
| 215 | if line != "" { |
| 216 | return line |
| 217 | } |
| 218 | } |
| 219 | } |
| 220 | return "unknown" |
| 221 | } |
no outgoing calls
no test coverage detected