Skip to content
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: error reading Stdin on windows #13697

Closed
alexbrainman opened this issue Dec 21, 2015 · 20 comments
Closed

os: error reading Stdin on windows #13697

alexbrainman opened this issue Dec 21, 2015 · 20 comments
Milestone

Comments

@alexbrainman
Copy link
Member

@alexbrainman alexbrainman commented Dec 21, 2015

I tried to verify if recently closed issue #6303 is fixed, but the program mentioned in the issue is broken now:

C:\dev\src\a>go version
go version devel +97f854c Sat Dec 19 10:00:04 2015 +0000 windows/386

C:\dev\src\a>type foo.go
package main

import (
        "fmt"
        "io"
        "os"
)

func main() {
        n, err := io.Copy(os.Stdout, os.Stdin)
        fmt.Printf("n=%d err=%v\n", n, err)
}

C:\dev\src\a>go build foo.go && foo.exe
n=0 err=read /dev/stdin: Not enough storage is available to process this command.

C:\dev\src\a>

Alex

@mattn
Copy link
Member

@mattn mattn commented Dec 21, 2015

I can't reproduce it.

@alexbrainman
Copy link
Member Author

@alexbrainman alexbrainman commented Dec 23, 2015

It is syscall.ReadFile returns ERROR_NOT_ENOUGH_MEMORY. I can reproduce it on my both winxp and windows 7.

Alex

@alexbrainman alexbrainman added this to the Go1.6 milestone Dec 23, 2015
@mattn
Copy link
Member

@mattn mattn commented Dec 23, 2015

I'm also using windows7. Is it related issue of 32bit/64bit?

@alexbrainman
Copy link
Member Author

@alexbrainman alexbrainman commented Dec 24, 2015

Is it related issue of 32bit/64bit?

My windows xp is 32bit, and my windows 7 is 64bit.

Alex

@mattn
Copy link
Member

@mattn mattn commented Dec 28, 2015

This is not reproduced on Windows7 32bit.

@azdagron
Copy link
Contributor

@azdagron azdagron commented Jan 4, 2016

I also cannot reproduce on Windows 10 64-bit using the 1.6beta1 build:

Microsoft Windows [Version 10.0.10586]
(c) 2015 Microsoft Corporation. All rights reserved.

C:\dev\src\a>go version
go version go1.6beta1 windows/amd64

C:\dev\src\a>type foo.go
package main

import (
        "fmt"
        "io"
        "os"
)

func main() {
        n, err := io.Copy(os.Stdout, os.Stdin)
        fmt.Printf("n=%d err=%v\n", n, err)
}

C:\dev\src\a>go build foo.go && foo.exe
This
This
is
is
a
a
test.
test.
^Z
n=20 err=<nil>
@alexbrainman
Copy link
Member Author

@alexbrainman alexbrainman commented Jan 5, 2016

More information. This fails only if my executable is windows-386 - it fails on both 32bit windows xp and 64bit my windows 7. It works as expected if executable is windows-amd64.

Alex

@rsc
Copy link
Contributor

@rsc rsc commented Jan 7, 2016

From https://msdn.microsoft.com/en-us/library/windows/desktop/aa365467(v=vs.85).aspx

The ReadFile function may fail with ERROR_INVALID_USER_BUFFER or ERROR_NOT_ENOUGH_MEMORY whenever there are too many outstanding asynchronous I/O requests.

I don't see how that's possible, of course, since this is the first read in the entire program.

Actually http://microsoft.public.win32.programmer.kernel.narkive.com/A5Q9kG7J/reading-console-input suggests the maximum size you can read from the console is "0x77E8".

Can you try this diff:

diff --git a/src/os/file_windows.go b/src/os/file_windows.go
index bda495e..f260a72 100644
--- a/src/os/file_windows.go
+++ b/src/os/file_windows.go
@@ -264,9 +264,9 @@ func (f *File) readConsole(b []byte) (n int, err error) {
    }
    if len(f.readbuf) == 0 {
        numBytes := len(b)
-       // Windows  can't read bytes over max of int16.
-       if numBytes > 32767 {
-           numBytes = 32767
+       // Windows can't read bytes over max of int16.
+       if numBytes > 30000 {
+           numBytes = 30000
        }
        mbytes := make([]byte, numBytes)
        var nmb uint32
@alexbrainman
Copy link
Member Author

@alexbrainman alexbrainman commented Jan 7, 2016

Can you try this diff:

That does not help. You should be able to reproduce this yourself even on windows-amd64 - you just need to build windows-386 exe.

Alex

@rsc
Copy link
Contributor

@rsc rsc commented Jan 7, 2016

@mattn
Copy link
Member

@mattn mattn commented Jan 7, 2016

@alexbrainman I tried the patch with GOARCH=386. When numBytes is 32767, I reproduce it.

But

diff --git a/src/os/file_windows.go b/src/os/file_windows.go
index bda495e..ed02962 100644
--- a/src/os/file_windows.go
+++ b/src/os/file_windows.go
@@ -265,8 +265,8 @@ func (f *File) readConsole(b []byte) (n int, err error) {
    if len(f.readbuf) == 0 {
        numBytes := len(b)
        // Windows  can't read bytes over max of int16.
-       if numBytes > 32767 {
-           numBytes = 32767
+       if numBytes > 30000 {
+           numBytes = 30000
        }
        mbytes := make([]byte, numBytes)
        var nmb uint32

When numBytes = 30000, it fixes this.

@mattn
Copy link
Member

@mattn mattn commented Jan 7, 2016

I tried this on windows7 64bit. And go build with set GOARCH=386.

@alexbrainman
Copy link
Member Author

@alexbrainman alexbrainman commented Jan 7, 2016

@mattn it does not fixes it fro me on Windows XP windows-386.

Alex

@mattn
Copy link
Member

@mattn mattn commented Jan 7, 2016

@alexbrainman if the numBytes is more fewer, how it work?

@alexbrainman
Copy link
Member Author

@alexbrainman alexbrainman commented Jan 7, 2016

@alexbrainman if the numBytes is more fewer, how it work?

Which numBytes do you want me to try? If you give me a number, I will try.

Alex

@alexbrainman
Copy link
Member Author

@alexbrainman alexbrainman commented Jan 8, 2016

28672 please

Same result. Still broken.

Alex

@rsc
Copy link
Contributor

@rsc rsc commented Jan 8, 2016

I don't know what's going on, but it's certainly not wrong to read fewer bytes, and this does help on some systems, so I am going to send a CL lowering the max. It's not going to matter too much whether we read 32,000 or even 10,000 chars at a time from the console.

rsc added a commit that referenced this issue Jan 8, 2016
Reading 32,767 is too many on some versions of Windows.
The exact upper bound is unclear.

For #13697, but may not fix the problem on all systems.

Change-Id: I197021ed60cbcd33c91ca6ceed456ec3d5a6c9d6
Reviewed-on: https://go-review.googlesource.com/18433
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
@alexbrainman
Copy link
Member Author

@alexbrainman alexbrainman commented Jan 9, 2016

Now my program above works on both 386 and amd64. I will let @rsc decide what to do next.

Alex

@rsc
Copy link
Contributor

@rsc rsc commented Jan 13, 2016

I'm a little confused but it sounds like no one has a program that fails anymore. Sounds fixed to me!

@rsc rsc closed this Jan 13, 2016
@golang golang locked and limited conversation to collaborators Jan 13, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
5 participants
You can’t perform that action at this time.