New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cmd/go,os: EAGAIN
when writing to stdout/stderr during test
#58408
Comments
I'm surprised that a write to What was the exact How reproducible is this failure mode? (CC @ianlancetaylor) |
EAGAIN
when writing to stdout/stderr during test
One more question: what version of Linux (and what container environment, if any) is the test running under? |
It looks like In the child process,
So the only way I see for an I see a path on which that may be possible:
So my hypothesis is that somehow |
EAGAIN
when writing to stdout/stderr during testEAGAIN
when writing to stdout/stderr during test
I've managed to narrow this down somewhat: // print_test.go
package print_test
import (
"bufio"
"bytes"
"fmt"
"os"
"os/exec"
"testing"
)
func TestPrint(t *testing.T) {
cmd := exec.Command("npx", "hardhat", "run", "--no-compile", "test.js")
stdout, err := cmd.StdoutPipe()
check(err)
cmd.Stderr = os.Stderr
outReader := bufio.NewReader(stdout)
check(cmd.Start())
_, err = outReader.ReadBytes('\n')
check(err)
var buf bytes.Buffer
for i := 0; i < 100_000; i++ {
fmt.Fprintf(&buf, "%04d\n", i)
}
s := buf.String()
fmt.Fprintf(os.Stderr, "about to write %d bytes\n", len(s))
if _, err := fmt.Fprint(os.Stderr, s); err != nil {
panic(err)
}
}
func check(err error) {
if err != nil {
panic(err)
}
} // test.js
async function main() {
console.log('1');
await delay(1000);
}
main().catch((err) => {
console.error(err);
process.exit(1);
});
function delay(time) {
return new Promise(resolve => setTimeout(resolve, time));
} Run with
Observed output
OS Version: Linux Mint 21 (Vanessa)
No containers/sandboxing. |
isn't that a race on the stderr resource?
|
Thanks for the complete test case. Unfortunately, I can't recreate the problem. My first guess would be that the |
It does seem to be the case that nodejs sometimes puts stdout/err into non-blocking mode. Removing the The purpose of this line is to forward error/log messages from the child and make them show up in the terminal. It's not really an issue if the child process and the main one write to stderr at the same time so I wouldn't consider it a race condition. |
@ianlancetaylor, it occurs to me that Go probably causes the dual problem itself in |
For the particular symptom at hand, would it be feasible to either always initialize runtime polling support in |
I think you're right: we do seem to lose track of the fact that the descriptor passed to Detecting @adob Given the behavior of nodejs here, I recommend that you not to try share stderr between the Go program and the nodejs program. It is straightforward to add (untested) stderr, err := cmd.StderrPipe()
check(err)
go func() { io.Copy(os.Stderr, stderr) }() |
A simpler workaround might be: cmd.Stderr = struct{ *os.File }{os.Stderr} which I think should cause the |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
Calls to
fmt.Printf()
during test fail with/dev/stdout: resource temporarily unavailable
when printing long lines after part of the output has been printed. The output is truncated.This can be worked around by passing the
-bench
flag to suppress output redirection during test execution.The text was updated successfully, but these errors were encountered: