-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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
os: buffer not flushed correctly #25631
Comments
You aren't checking the error return of the Do you see the same behavior from an identical C program? |
Please post |
So here is the code with the error check on Close (there is no error showing up) https://play.golang.org/p/9vEmEpSuXK_b I didn't try in C as I wouldn't remember how to do that ;) |
BTW by writing straight to the file it works (os.File.WriteString()), it's just through the buffer that it eats the end even though the code is executed and I see the iobuf.Buffered() growing as expected. |
May it be due to this change introduced in 1.9 IIUC? I mean, from the
is operating on the FD 3, which is the same FD, |
The behaviour definitely changed from 1.9 so it's very possible |
Looks like all the 81 bytes were written. |
@ianlancetaylor, thoughts on how the runtime poller for files would affect this? |
I wonder how the May it be that there it would not be written as a single chunk? |
I agree with @opennota : the strace output clearly shows that all 81 bytes were written to the file, and then the file is closed without error. The effect of the change to use the runtime poller is that the file is put into nonblocking mode which shows up in the strace as If it weren't for that discrepancy, I would guess that there is a bug in the kernel driver when the descriptor is in non-blocking mode: I would guess that it is incorrectly reporting that all the bytes were written, when only some were. It is also possible that in nonblocking mode the kernel queues the bytes for writing, returns before they are sent to the hardware, and then aborts the queued bytes when the descriptor is closed. However that too is not consistent with different behavior when using The simple workaround may be to call the |
@ianlancetaylor, do I understand you correctly that by saying
you mean that it had to return |
I should make clear that I am only speculating, I haven't looked at the code. And thinking about it a bit more, my speculation can't be right, since all the bytes are written out if the program waits a few seconds. So maybe the problem is that the close system call is aborting any queued bytes, when it should instead wait until they are written. But again I am only speculating. I don't know what is happening. But I do still suspect that there is some bug in the kernel driver. |
So, may be the answer is to make sure that the FD is put back into the blocking mode The reasoning is as follows:
(Emphasis mine.) And this suggests The A quick test would be to copy the implementation of |
It seems to me that even if |
Since the strace shows that all the bytes are written to the kernel, I'm very skeptical that there is anything we can do in Go to fix this. I'm going to close this issue. Please comment if you disagree. |
Please answer these questions before submitting your issue. Thanks!
What version of Go are you using (
go version
)?I ran the code on multiple versions:
It works on v1.7.5 and v1.8.7
It fails on v1.9, v1.9.4, v1.9.6 and v1.10.2
Does this issue reproduce with the latest release?
Yes (1.10.2)
What operating system and processor architecture are you using (
go env
)?GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/theute/.go"
GORACE=""
GOROOT="/home/theute/Tools/Go/latest"
GOTOOLDIR="/home/theute/Tools/Go/latest/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build923971487=/tmp/go-build -gno-record-gcc-switches"
CXX="g++"
CGO_ENABLED="1"
PKG_CONFIG="pkg-config"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
What did you do?
I'm writing to the USB device of my linux machine /dev/usb/lp0 to a printer. (I tried on my laptop and a raspberry)
The code is https://play.golang.org/p/7J8srsKSzSf
What did you expect to see?
It should have printed up to "test-11"
What did you see instead?
It stopped printing at "test-8" with no error.
If I compile with v1.7.5 or v1.8.7 then it prints everything
Note: If I add a 5s sleep at the end of the print method then it prints everything. But if I call the print method followed by a call to Sleep it will not help.
The text was updated successfully, but these errors were encountered: