@@ -13,6 +13,7 @@ import (
13
13
"io"
14
14
"log"
15
15
"os"
16
+ "reflect"
16
17
"regexp"
17
18
"runtime"
18
19
"strconv"
@@ -216,6 +217,18 @@ func (i *Invocation) run(ctx context.Context, stdout, stderr io.Writer) error {
216
217
cmd := exec .Command ("go" , goArgs ... )
217
218
cmd .Stdout = stdout
218
219
cmd .Stderr = stderr
220
+
221
+ // cmd.WaitDelay was added only in go1.20 (see #50436).
222
+ if waitDelay := reflect .ValueOf (cmd ).Elem ().FieldByName ("WaitDelay" ); waitDelay .IsValid () {
223
+ // https://go.dev/issue/59541: don't wait forever copying stderr
224
+ // after the command has exited.
225
+ // After CL 484741 we copy stdout manually, so we we'll stop reading that as
226
+ // soon as ctx is done. However, we also don't want to wait around forever
227
+ // for stderr. Give a much-longer-than-reasonable delay and then assume that
228
+ // something has wedged in the kernel or runtime.
229
+ waitDelay .Set (reflect .ValueOf (30 * time .Second ))
230
+ }
231
+
219
232
// On darwin the cwd gets resolved to the real path, which breaks anything that
220
233
// expects the working directory to keep the original path, including the
221
234
// go command when dealing with modules.
@@ -230,6 +243,7 @@ func (i *Invocation) run(ctx context.Context, stdout, stderr io.Writer) error {
230
243
cmd .Env = append (cmd .Env , "PWD=" + i .WorkingDir )
231
244
cmd .Dir = i .WorkingDir
232
245
}
246
+
233
247
defer func (start time.Time ) { log ("%s for %v" , time .Since (start ), cmdDebugStr (cmd )) }(time .Now ())
234
248
235
249
return runCmdContext (ctx , cmd )
0 commit comments