]> Cypherpunks repositories - gostls13.git/commitdiff
os: use small writes during console io
authorAlex Brainman <alex.brainman@gmail.com>
Wed, 19 Sep 2012 06:55:21 +0000 (16:55 +1000)
committerAlex Brainman <alex.brainman@gmail.com>
Wed, 19 Sep 2012 06:55:21 +0000 (16:55 +1000)
Fixes #3767

R=golang-dev, bradfitz, rsc
CC=golang-dev
https://golang.org/cl/6523043

src/pkg/os/file_windows.go
src/pkg/os/os_test.go

index 9e0da5ae812fb262ae3b285f6be021dff06771b8..a86b8d61cd9adc0f7eb2dd44c37bb19446f57575 100644 (file)
@@ -258,8 +258,18 @@ func (f *File) writeConsole(b []byte) (n int, err error) {
                f.lastbits = make([]byte, len(b))
                copy(f.lastbits, b)
        }
-       if len(runes) > 0 {
-               uint16s := utf16.Encode(runes)
+       // syscall.WriteConsole seems to fail, if given large buffer.
+       // So limit the buffer to 16000 characters. This number was
+       // discovered by experimenting with syscall.WriteConsole.
+       const maxWrite = 16000
+       for len(runes) > 0 {
+               m := len(runes)
+               if m > maxWrite {
+                       m = maxWrite
+               }
+               chunk := runes[:m]
+               runes = runes[m:]
+               uint16s := utf16.Encode(chunk)
                for len(uint16s) > 0 {
                        var written uint32
                        err = syscall.WriteConsole(f.fd, &uint16s[0], uint32(len(uint16s)), &written, nil)
index 14b4837a0484420267e554e8e495926b24d1a48f..1940f562def795da3dbfaeec4867d53979f04524 100644 (file)
@@ -6,6 +6,7 @@ package os_test
 
 import (
        "bytes"
+       "flag"
        "fmt"
        "io"
        "io/ioutil"
@@ -1066,3 +1067,31 @@ func TestDevNullFile(t *testing.T) {
                t.Fatalf("wrong file size have %d want 0", fi.Size())
        }
 }
+
+var testLargeWrite = flag.Bool("large_write", false, "run TestLargeWriteToConsole test that floods console with output")
+
+func TestLargeWriteToConsole(t *testing.T) {
+       if !*testLargeWrite {
+               t.Logf("skipping console-flooding test; enable with -large_write")
+               return
+       }
+       b := make([]byte, 32000)
+       for i := range b {
+               b[i] = '.'
+       }
+       b[len(b)-1] = '\n'
+       n, err := Stdout.Write(b)
+       if err != nil {
+               t.Fatalf("Write to os.Stdout failed: %v", err)
+       }
+       if n != len(b) {
+               t.Errorf("Write to os.Stdout should return %d; got %d", len(b), n)
+       }
+       n, err = Stderr.Write(b)
+       if err != nil {
+               t.Fatalf("Write to os.Stderr failed: %v", err)
+       }
+       if n != len(b) {
+               t.Errorf("Write to os.Stderr should return %d; got %d", len(b), n)
+       }
+}