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

ANSI terminal emulation for windows #10864

Closed

Conversation

@sachin-jayant-joshi
Copy link
Contributor

@sachin-jayant-joshi sachin-jayant-joshi commented Feb 17, 2015

Background

The Linux console implements a large subset of the VT102 and ECMA-48/ISO 6429/ANSI X3.64 terminal controls, plus certain private-mode sequences for changing the color palette, character-set mapping, and so on.

However similar standard is not natively available in Windows Console and therefore the various escape sequences are not interpreted and the output looks unformatted and garbled.

This change implements the functionality to emulate the Linux console escape sequences on Windows console by intercepting the terminal output and calling appropriate win32 functions to actualize the console control commands.

ANSI functionality implemented

• Translating keystroke events to appropriate ANSI sequences
• Text color and attributes
• Cursor movement
• Erasing parts of the screen

High Level Design

  • Implement io.Writer and io.ReadCloser interfaces in two structs terminalWriter and terminalReader.
    • When docker cli is initialized in NewDockerCli function, on windows we use these wrapper reader/writers. But for the other operating systems we continue to use standard reader/writers as before .
      • Under the hood these wrapper classes parse the incoming/outgoing byte streams, extract that ANSI command and call the appropriate APIs.
      • The rest of the docker code need not to know whether or how the byte streams are intercepted and interpreted.
  • The actual reading from and writing to the windows console is done in WindowsTerminal struct.
    • This functionality is exposed to terminalWriter and terminalReader through an interface terminalEmulator
      • HandleOutputCommand(command []byte) (n int, err error) : Takes appropriate action for the given ansi command
      • WriteChars(w io.Writer, p []byte) (n int, err error): Writes Characters to console output
      • ReadChars(w io.Reader, p []byte) (n int, err error): Reads Characters from keyboard
  • Much of the implementation of HandleOutputCommand involves first parsing the ANSI command, and then translating commands and their parameters to series of Win32 APIs calls.
  • The output is buffered to accommodate when the command sequences are divided between more than one consecutive write calls.
  • Similarly while reading keystokes, all available input events are “consumed” by first translating them to appropriate ANSI sequences , but returning only the requested number of bytes and buffering the rest.

Limitations

The approach depends on re-implementing the entire ANSI and other standards that Linux implements.
This is not practical and therefore just enough functionality is implemented to make it usable for 90% of the cases.

Known Issues

  • Terminal size issues
    • Terminal resize is not supported.
    • The host always thinks that the terminal is 80 x 24. This code does not attempt to configure it to match console size on windows.
  • The RBG values for basic ansi color palette cannot be selected.
  • Simulating Linux signals and Interrupt handling is not implemented.

References

  1. Manual for Linux console : http://man7.org/linux/man-pages/man4/console_codes.4.html
  2. Documentation for windows console functionality : https://msdn.microsoft.com/en-us/library/windows/desktop/ms682087(v=vs.85).aspx

cc: @shykes @icecrime @vieux @tiborvass @ahmetalpbalkan @johngossman

@tiborvass
Copy link
Collaborator

@tiborvass tiborvass commented Feb 18, 2015

<3

@SvenDowideit
Copy link
Contributor

@SvenDowideit SvenDowideit commented Feb 18, 2015

💃

@ahmetb
Copy link
Contributor

@ahmetb ahmetb commented Feb 18, 2015

this is Dr. Nyan Cat, and this PR is terminal...

@nathanleclaire
Copy link
Contributor

@nathanleclaire nathanleclaire commented Feb 19, 2015

👏 👏 👏

type Terminal struct {
StdOut io.Writer
StdErr io.Writer
StdIn io.ReadCloser
Copy link
Collaborator

@tiborvass tiborvass Feb 19, 2015

Maybe we should rename Terminal to Stdio. This is not a terminal in the TTY sense.
Ping @sachin-jayant-joshi @ahmetalpbalkan

Copy link
Collaborator

@tiborvass tiborvass Feb 20, 2015

@sachin-jayant-joshi I would like to make sure that we don't translate ANSI stuff if stdout is not a tty, and have a test for that.

Copy link
Contributor Author

@sachin-jayant-joshi sachin-jayant-joshi Feb 20, 2015

I agree that it could be a better name.

VT1002 was an actual terminal and There are many places where VT100 and ANSI are used synonymously.
In fact http://en.wikipedia.org/wiki/VT100
"The VT100 is a video terminal, introduced in August 1978 ....
...This led to rapid uptake of the ANSI standard, becoming the de facto standard for terminal emulators."

I think for the programmers coming from c/c++ background (like me), the name stdio has a specific connotation. Here I want to capture the concept of bundling together of stdin+stdout+stderr so used the name Terminal.

How about "Console" ?

A slight diversion --
(A bit of interesting history .."The Linux console was one of the first features of the kernel and was originally written by Linus Torvalds in 1991[4]"
http://en.wikipedia.org/wiki/Linux_console
http://en.wikipedia.org/wiki/Linux_console#Control_characters

Copy link
Contributor

@ahmetb ahmetb Feb 20, 2015

@sachin-jayant-joshi can we please write an integration-cli test case that verifies if docker run ubuntu grep root /etc/passwd | cat -e is exactly the same as the one we get on linux? @tibor suggested this on IRC.

Copy link
Contributor Author

@sachin-jayant-joshi sachin-jayant-joshi Feb 20, 2015

@tiborvass I agree, I will double check that when stdout is redirected the escape sequence is not filtered out.
@ahmetalpbalkan Lets figure out a way to implement this test on Windows as windows does not have cat.

Copy link
Contributor

@ahmetb ahmetb Feb 20, 2015

@sachin-jayant-joshi our CI tests are running inside msys bash, it does have cat. We should be able to implement it. +1 on this, it's better to have a test case because someone might modify it by not realizing the possible outcome unless it's not covered with a test.

@jessfraz
Copy link
Contributor

@jessfraz jessfraz commented Feb 21, 2015

So for fun we tried to run a container with a nyan cat in cmd.exe

docker run -it --rm supertest2014/nyan

http://pastebin.com/daJEzAK0

we do know that it may not work for the nyan cat ;)

@jessfraz
Copy link
Contributor

@jessfraz jessfraz commented Feb 21, 2015

but colors on ls work ;) so yayyyyyyyy!

same with ^A, ^E, ^R, ^W YAYYYYYY LGTM

@sachin-jayant-joshi sachin-jayant-joshi force-pushed the windows-tty branch 2 times, most recently from 399a4bd to 699cc53 Feb 25, 2015
@sachin-jayant-joshi
Copy link
Contributor Author

@sachin-jayant-joshi sachin-jayant-joshi commented Feb 25, 2015

amended the commit with the changes requested.

  • removed the terminal struct,
  • checking if stream is redirected or not
  • fixed some issues with nyan (fixed bufferio panic),
  • In addition using channel for buffering keystrokes.

@tiborvass
Copy link
Collaborator

@tiborvass tiborvass commented Feb 25, 2015

What do you guys think of:

// +build windows

package main

func init() {
  os.Stdin = term.Convert(os.Stdin)
  os.Stdout = term.Convert(os.Stdout)
  os.Stderr = term.Convert(os.Stderr)
}

Ping @tianon

@jessfraz
Copy link
Contributor

@jessfraz jessfraz commented Feb 25, 2015

ooooo that looks nice

On Wed, Feb 25, 2015 at 1:26 PM, Tibor Vass notifications@github.com
wrote:

What do you guys think of:

// +build windowspackage main
func init() {
os.Stdin = term.Convert(os.Stdin)
os.Stdout = term.Convert(os.Stdout)
os.Stderr = term.Convert(os.Stderr)
}

Ping @tianon https://github.com/tianon


Reply to this email directly or view it on GitHub
#10864 (comment).

@ahmetb
Copy link
Contributor

@ahmetb ahmetb commented Feb 25, 2015

@tiborvass +1 for the idea of wrapping but I hate the init() part, it makes things pretty undiscoverable. (something magically executed and had some global side effects in the program at some point in the history) I just prefer passing wrapped streams to the term methods.

@sachin-jayant-joshi awesome thanks! it's no big deal but I'm having some issues which we should probably address in next PRs.

  • CTRL+left/right arr keys on docker run -it ubuntu bash print 5D/5C to screen rather than moving the cursor.
  • Pressing Home key and keep typing behaves like INS but when I press End key, the text gets corrected just like it wasn't in Insert mode.
  • Running docker.exe resizes my terminal to 80x26 without asking (kinda frustrating if we can avoid, I'm even file with showing a 80x26 output in a bigger term window)

VK_INSERT: "\x1B[2%s~",
VK_DELETE: "\x1B[3%s~",
VK_PRIOR: "\x1B[5%s~",
VK_NEXT: "\x1B[6%s~",
Copy link
Contributor Author

@sachin-jayant-joshi sachin-jayant-joshi Feb 25, 2015

The keys are supposed to be translated to a specific escape sequences.
If any of the keys is not working as expected then perhaps mapping is wrong

As for the specific translation of keystrokes for arrows - the vi specifically asks for sending application mapping and that is what we send.
Can I take this as a specific bug and fix it later in a smaller PR for bug fixes?

@tiborvass
Copy link
Collaborator

@tiborvass tiborvass commented Mar 4, 2015

@sachin-jayant-joshi

When I use docker -D version with an incorrect DOCKER_HOST, I get a FATA error, but that FATA is supposed to be red. It is red if I do docker version though.

Z:\windows>docker-1.5.0-dev.exe version
Client version: 1.5.0-dev
Client API version: 1.18
Go version (client): go1.4.1
Git commit (client): 699cc53
OS/Arch (client): windows/amd64
FATA[0000] An error occurred trying to connect: Get https:///var/run/docker.sock/v1.18/version: dial unix /var/run/docker.sock: An address incompatible with the requested protocol was used.

Z:\windows>docker-1.5.0-dev.exe -D version
Client version: 1.5.0-dev
Client API version: 1.18
Go version (client): go1.4.1
Git commit (client): 699cc53
OS/Arch (client): windows/amd64
←[31mFATA←[0m[0000] An error occurred trying to connect: Get https:///var/run/docker.sock/v1.18/version: dial unix /var/run/docker.sock: An address incompatible with the requested protocol was used.

The reason for that is because in docker/log.go we reset the log output to os.Stderr. Not sure what would be the best refactoring but some refactoring is needed.

Also: it would be really nice to have the ANSI translations for repositioning the cursor, so that docker pull busybox the first time, shows the progress bar.

When I tried to use vi, it gave me a weird error.

Z:\windows>docker-1.5.0-dev.exe run -it busybox vi
FATA[0000] The parameter is incorrect.

Z:\windows>docker-1.5.0-dev.exe -D run -it busybox vi
←[34mDEBU←[0m[0000] [hijack] End of stdout
←[34mDEBU←[0m[0000] Error receiveStdout: The parameter is incorrect.
←[34mDEBU←[0m[0000] Error hijack: The parameter is incorrect.
←[34mDEBU←[0m[0000] End of CmdRun(), Waiting for hijack to finish.
←[31mFATA←[0m[0000] The parameter is incorrect.

And finally, I managed to get a panic I don't really know how (tried to reproduce it, I manage to do it quite often, but could not find a consistent way): I do something like l, then Tab (couple of times) and then Ctrl+D. Can be a variation of those.

/ # lunexpected fault address 0xffffffffffffffff
fatal error: fault
[signal 0xc0000005 code=0x0 addr=0xffffffffffffffff pc=0x411271]

goroutine 12 [running]:
runtime.gothrow(0x88bf90, 0x5)
        /usr/local/go/src/runtime/panic.go:503 +0x8e fp=0xc0820937d8 sp=0xc0820937c0
runtime.sigpanic()
        /usr/local/go/src/runtime/os_windows.go:45 +0x118 fp=0xc0820937f8 sp=0xc0820937d8
runtime.mallocgc(0x4, 0x0, 0x3, 0xc0820e000c)
        /usr/local/go/src/runtime/malloc.go:152 +0x201 fp=0xc0820938a8 sp=0xc0820937f8
runtime.rawstring(0x4, 0x0, 0x0, 0x0, 0x0, 0x0)
        /usr/local/go/src/runtime/string.go:195 +0x9a fp=0xc0820938d8 sp=0xc0820938a8
runtime.intstring(0x20, 0x0, 0x0)
        /usr/local/go/src/runtime/string.go:149 +0x40 fp=0xc082093938 sp=0xc0820938d8
github.com/docker/docker/pkg/term.clearDisplayRect(0x24, 0x900000007db20, 0x4b007800490077, 0x73005c7b01, 0x0, 0x0)
        /go/src/github.com/docker/docker/pkg/term/console_windows.go:432 +0x120 fp=0xc0820939e0 sp=0xc082093938
github.com/docker/docker/pkg/term.clearDisplayRange(0x24, 0x800050007a020, 0x4b0078004a0077, 0x0, 0x0, 0x0)
        /go/src/github.com/docker/docker/pkg/term/console_windows.go:477 +0x34f fp=0xc082093a50 sp=0xc0820939e0
github.com/docker/docker/pkg/term.(*WindowsTerminal).HandleOutputCommand(0xc08209a700, 0xc082074000, 0x3, 0x100, 0x0, 0x                                                         0, 0x0)
        /go/src/github.com/docker/docker/pkg/term/console_windows.go:778 +0xd66 fp=0xc082093c30 sp=0xc082093a50
github.com/docker/docker/pkg/term.(*terminalWriter).Write(0xc08209a800, 0xc082087000, 0xdd, 0x1000, 0xdd, 0x0, 0x0)
        /go/src/github.com/docker/docker/pkg/term/term_emulator.go:94 +0x3c9 fp=0xc082093d48 sp=0xc082093c30
bufio.(*Reader).writeBuf(0xc08203a780, 0x1d22d8, 0xc08209a800, 0xdd, 0x0, 0x0)
        /usr/local/go/src/bufio/bufio.go:463 +0xac fp=0xc082093db0 sp=0xc082093d48
bufio.(*Reader).WriteTo(0xc08203a780, 0x1d22d8, 0xc08209a800, 0x16f5, 0x0, 0x0)
        /usr/local/go/src/bufio/bufio.go:444 +0x230 fp=0xc082093e28 sp=0xc082093db0
io.Copy(0x1d22d8, 0xc08209a800, 0x1d4730, 0xc08203a780, 0x0, 0x0, 0x0)
        /usr/local/go/src/io/io.go:354 +0xb9 fp=0xc082093ee0 sp=0xc082093e28
github.com/docker/docker/api/client.func┬╖023(0x0, 0x0)
        /go/src/github.com/docker/docker/api/client/hijack.go:210 +0x1e0 fp=0xc082093fa8 sp=0xc082093ee0
github.com/docker/docker/pkg/promise.func┬╖001()
        /go/src/github.com/docker/docker/pkg/promise/promise.go:8 +0x36 fp=0xc082093fe0 sp=0xc082093fa8
runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:2232 +0x1 fp=0xc082093fe8 sp=0xc082093fe0
created by github.com/docker/docker/pkg/promise.Go
        /go/src/github.com/docker/docker/pkg/promise/promise.go:9 +0x102

goroutine 1 [chan receive]:
github.com/docker/docker/api/client.(*DockerCli).CmdRun(0xc0820fc280, 0xc0820061e0, 0x2, 0x2, 0x0, 0x0)
        /go/src/github.com/docker/docker/api/client/commands.go:2359 +0xe56
reflect.callMethod(0xc0820f4ff0, 0xc08203dbe8)
        /usr/local/go/src/reflect/value.go:605 +0x180
reflect.methodValueCall(0xc0820061e0, 0x2, 0x2, 0x1, 0xc0820f4ff0, 0xc0820fc301, 0xc0820e81b0, 0x5, 0xc08209a800, 0x1c5e                                                         e0, ...)
        /usr/local/go/src/reflect/asm_amd64.s:29 +0x3d
github.com/docker/docker/api/client.(*DockerCli).Cmd(0xc0820fc280, 0xc0820061d0, 0x3, 0x3, 0x0, 0x0)
        /go/src/github.com/docker/docker/api/client/cli.go:81 +0x385
main.main()
        /go/src/github.com/docker/docker/docker/docker.go:133 +0xb6d

goroutine 5 [syscall]:
os/signal.loop()
        /usr/local/go/src/os/signal/signal_unix.go:21 +0x26
created by os/signal.init┬╖1
        /usr/local/go/src/os/signal/signal_unix.go:27 +0x3c

goroutine 11 [chan receive]:
github.com/docker/docker/api/client.(*DockerCli).hijack(0xc0820fc280, 0x885c50, 0x4, 0xc08206c800, 0x76, 0x1, 0x1d2330,                                                          0xc08209a880, 0x1d22d8, 0xc08209a800, ...)
        /go/src/github.com/docker/docker/api/client/hijack.go:237 +0xd38
github.com/docker/docker/api/client.func┬╖014(0x0, 0x0)
        /go/src/github.com/docker/docker/api/client/commands.go:2326 +0x1fd
github.com/docker/docker/pkg/promise.func┬╖001()
        /go/src/github.com/docker/docker/pkg/promise/promise.go:8 +0x36
created by github.com/docker/docker/pkg/promise.Go
        /go/src/github.com/docker/docker/pkg/promise/promise.go:9 +0x102
fold               lspci              setconsole         xzcat
goroutine 9 [IO wait]:sb              setkeycodes        yes
net.(*pollDesc).Wait(0xc0820662f0, 0x72, 0x0, 0x0)       zcat
        /usr/local/go/src/net/fd_poll_runtime.go:84 +0x4e
net.(*ioSrv).ExecIO(0xc0820382d0, 0xc0820661e0, 0x8883f0, 0x7, 0x965258, 0x5d, 0x0, 0x0)
        /usr/local/go/src/net/fd_windows.go:188 +0x305
net.(*netFD).Read(0xc082066180, 0xc08202ac00, 0x400, 0x400, 0x0, 0x0, 0x0)
        /usr/local/go/src/net/fd_windows.go:470 +0x180
net.(*conn).Read(0xc0820382e8, 0xc08202ac00, 0x400, 0x400, 0x0, 0x0, 0x0)
        /usr/local/go/src/net/net.go:121 +0xe3
crypto/tls.(*block).readFromUntil(0xc0820f4bd0, 0x1d3db0, 0xc0820382e8, 0x5, 0x0, 0x0)
        /usr/local/go/src/crypto/tls/conn.go:454 +0xed
crypto/tls.(*Conn).readRecord(0xc0820842c0, 0x17, 0x0, 0x0)
        /usr/local/go/src/crypto/tls/conn.go:539 +0x2e1
crypto/tls.(*Conn).Read(0xc0820842c0, 0xc08200f000, 0x1000, 0x1000, 0x0, 0x0, 0x0)
        /usr/local/go/src/crypto/tls/conn.go:904 +0x16d
net/http.noteEOFReader.Read(0x1d44f0, 0xc0820842c0, 0xc0820b81b8, 0xc08200f000, 0x1000, 0x1000, 0xc0820fe4c0, 0x0, 0x0)
        /usr/local/go/src/net/http/transport.go:1270 +0x75
net/http.(*noteEOFReader).Read(0xc082068640, 0xc08200f000, 0x1000, 0x1000, 0xc082012000, 0x0, 0x0)
        <autogenerated>:125 +0xdb
bufio.(*Reader).fill(0xc08203a900)
        /usr/local/go/src/bufio/bufio.go:97 +0x1d5
bufio.(*Reader).Peek(0xc08203a900, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0)
        /usr/local/go/src/bufio/bufio.go:132 +0xf7
net/http.(*persistConn).readLoop(0xc0820b8160)
        /usr/local/go/src/net/http/transport.go:842 +0xab
created by net/http.(*Transport).dialConn
        /usr/local/go/src/net/http/transport.go:660 +0xca6

goroutine 10 [select]:
net/http.(*persistConn).writeLoop(0xc0820b8160)
        /usr/local/go/src/net/http/transport.go:945 +0x424
created by net/http.(*Transport).dialConn
        /usr/local/go/src/net/http/transport.go:661 +0xcc3

goroutine 13 [runnable, locked to thread]:
syscall.(*Proc).Call(0xc0820fa160, 0xc082107c70, 0x4, 0x4, 0x2, 0x759b80, 0x0, 0x0)
        /usr/local/go/src/syscall/dll_windows.go:136 +0x5c2
syscall.(*LazyProc).Call(0xc08206a330, 0xc082107c70, 0x4, 0x4, 0xc0820ba000, 0x965498, 0x0, 0x0)
        /usr/local/go/src/syscall/dll_windows.go:279 +0x74
github.com/docker/docker/pkg/term.readConsoleInputKey(0x20, 0xc0820ba000, 0x400, 0x400, 0x400, 0x0, 0x0)
        /go/src/github.com/docker/docker/pkg/term/console_windows.go:543 +0xf4
github.com/docker/docker/pkg/term.getAvailableInputEvents(0x0, 0x0, 0x0, 0x0, 0x0)
        /go/src/github.com/docker/docker/pkg/term/console_windows.go:1039 +0xff
github.com/docker/docker/pkg/term.(*WindowsTerminal).ReadChars(0xc08209a700, 0x1d23b0, 0xc082038000, 0xc0820ec000, 0x800                                                         0, 0x8000, 0x0, 0x0, 0x0)
        /go/src/github.com/docker/docker/pkg/term/console_windows.go:1080 +0x13f
github.com/docker/docker/pkg/term.(*terminalReader).Read(0xc08209a880, 0xc0820ec000, 0x8000, 0x8000, 0x1, 0x0, 0x0)
        /go/src/github.com/docker/docker/pkg/term/term_emulator.go:151 +0x13b
io.Copy(0x1d4ab8, 0xc0820fa320, 0x1d4bd8, 0xc08209a880, 0x16, 0x0, 0x0)
        /usr/local/go/src/io/io.go:362 +0x1fd
github.com/docker/docker/api/client.func┬╖024(0x0, 0x0)
        /go/src/github.com/docker/docker/api/client/hijack.go:221 +0xe3
github.com/docker/docker/pkg/promise.func┬╖001()
        /go/src/github.com/docker/docker/pkg/promise/promise.go:8 +0x36
created by github.com/docker/docker/pkg/promise.Go
        /go/src/github.com/docker/docker/pkg/promise/promise.go:9 +0x102

Also I wonder whether we should emulate the ANSI console if os.Getenv("TERM") == "cygwin" (cc @ahmetalpbalkan @tianon )

@sachin-jayant-joshi
Copy link
Contributor Author

@sachin-jayant-joshi sachin-jayant-joshi commented Mar 4, 2015

@tiborvass Thanks a lot for looking into this and trying it out !!
I will try to repro the rest of the issues and fix them asap. (And do some more thorough testing as well)

[1] I agree that people will always use os.stderr or os.stdout etc directly and that we need global singleton objects that wrap ANSI functionality. I wish I could just go back and fix os package.
But in the mean time I think we can still use something likeglobal vars in term pkg : term.Stderr, term.Stdin, term.Stdout .

[2] parameter is incorrect - I think it is unlikely that this particular error is caused by ANSI code per se, will double check if it still repros without any ANSI processing.
[3] Panic is always bad - will try to repro and fix that. And thanks for finding it !!
[4] Regarding the Cygwin - I am not sure I completely understood what is the expected behavior.

cc @ahmetalpbalkan @tianon

@tianon
Copy link
Member

@tianon tianon commented Mar 4, 2015

@tiborvass
Copy link
Collaborator

@tiborvass tiborvass commented Mar 4, 2015

@sachin-jayant-joshi @tianon

I still think we should reset os.Stdout etc. on windows:

package main

import (
    "bufio"
    "fmt"
    "os"
)

var ch = make(chan struct{})

func init() {
    stdoutR, stdoutW, err := os.Pipe()
    if err != nil {
        panic(err)
    }

    os.Stdout = stdoutW

    go func() {
        scanner := bufio.NewScanner(stdoutR)
        for scanner.Scan() {
            line := scanner.Text()
            fmt.Fprintln(os.Stderr, "modified:", line)
        }
        close(ch)
    }()
}

func main() {
    defer func() {
        os.Stdout.Close()
        <-ch
    }()
    fmt.Println("Hello world")
}

Something like above. We would need to do that for Stdin and Stderr as well. We would also need to make sure IsTerminal(os.Stdout) returns true after modifying os.Stdout.

@tiborvass
Copy link
Collaborator

@tiborvass tiborvass commented Mar 4, 2015

@sachin-jayant-joshi @tianon what do you guys think of using this api instead https://gist.github.com/tiborvass/6d8e8662118dec4ca2ba

I think that will be the perfect API.

@sachin-jayant-joshi
Copy link
Contributor Author

@sachin-jayant-joshi sachin-jayant-joshi commented Mar 4, 2015

ok. I'll try that out.


// Save current screen buffer info
handle, _ := syscall.GetStdHandle(STD_OUTPUT_HANDLE)
screenBufferInfo, err := GetConsoleScreenBufferInfo(uintptr(handle))
Copy link
Collaborator

@tiborvass tiborvass Mar 4, 2015

what happens if err != nil ?

Copy link
Collaborator

@tiborvass tiborvass Mar 4, 2015

@sachin-jayant-joshi Also, this seems to be only necessary for HandleOutputCommand so I would put this under the IsTerminal(os.Stdout.Fd()) condition. Let me know if I'm mistaken!

Copy link
Contributor Author

@sachin-jayant-joshi sachin-jayant-joshi Mar 4, 2015

ok. That call can be probably avoided in case both stdout and stderr are redirected

This is also same - the value is used during clear display functionality. We need to use the console color that we started with to implement it. Eg Yellow foreground on blue background ..when you call "clear" on shell then need to use those colors. I think the problem might be that the method signature uses func (term *WindowsTerminal)

Signed-off-by: Sachin Joshi <sachin_jayant_joshi@hotmail.com>
Also rename func for non-windows specific names.

Signed-off-by: Sachin Joshi <sachin_jayant_joshi@hotmail.com>
// Set terminal emulation based on platform as required.
stdout, stderr, stdin := term.StdStreams()

initLogging(stderr)
Copy link
Contributor

@icecrime icecrime Mar 18, 2015

Just a question, but should be keep reexec.Init() the first thing? Some of the use of reexec being security related, I'm wondering if it wouldn't be safer to call the less possible code between main() invocation and actual reexec.

Any thoughts @tiborvass?

Copy link
Contributor Author

@sachin-jayant-joshi sachin-jayant-joshi Mar 18, 2015

@icecrime
I am not familiar with how reexec works. But my impression was that in case of the errors some of the initializers might write to the stderr. That was one reason why setting terminal and log output is done as soon as we can.

Copy link
Contributor

@icecrime icecrime Mar 18, 2015

You're right, but I'm not sure it's desirable.

Copy link
Collaborator

@tiborvass tiborvass Mar 19, 2015

I agree with icecrime, I would vote for putting this after the reexec.Init().

Following bugs are fixed:
1.Handle out of bound cursor movements: vi in busybox sets cursor
to (999,999) expecting it to be set to right, bottom correctly.

2.Correctly determine redirected non-terminal file.

Signed-off-by: Sachin Joshi <sachin_jayant_joshi@hotmail.com>
@icecrime
Copy link
Contributor

@icecrime icecrime commented Mar 18, 2015

I can confirm that the last commit properly fixes vi in busybox 👍

@ahmetb
Copy link
Contributor

@ahmetb ahmetb commented Mar 18, 2015

awesome, thanks @sachin-jayant-joshi

@tiborvass
Copy link
Collaborator

@tiborvass tiborvass commented Mar 19, 2015

Great job @sachin-jayant-joshi ! vi works indeed.

It seems I had a little harder time reproducing the panic I mentioned earlier, but still doing something similar, I managed to get the following:

/ # s
sed                setsid             sort               swapoff
seq                sh                 ss                 swapon
setarch            sha1sum            start-stop-daemon  switch_root
setconsole         sha256sum          strings            sync
setkeycodes        sha3sum            stty               sysctl
setlogcons         sha512sum          su                 syslogd
setserial          sleep              sulogin
/ # s
sed                setsid             sort               swapoff
seq                sh                 ss                 swapon
setarch            sha1sum            start-stop-daemon  switch_root
setconsole         sha256sum          strings            sync
setkeycodes        sha3sum            stty               sysctl
setlogcons         sha512sum          su                 syslogd
setserial          sleep              sulogin
/ # runtime: garbage collector found invalid heap pointer *(0xc08207ecd0+0x0)=0xc0820
70000 span=0xc082070000-0xc082071f80-0xc082072000 state=2
runtime: found *(0xc0820f0900+0x20) = 0xc08207ecd0+0x0
runtime: found *(0xc08208e480+0x268) = 0xc0820f0900+0x0
runtime: found *(0xc08207ee20+0x0) = 0xc08208e480+0x0
runtime: found *(0xc0820df420+0x0) = 0xc08207ee20+0x0
runtime: found *(0xc0820d0400+0x48) = 0xc0820df420+0x0
runtime: found *(0xc0820dc160+0x48) = 0xc0820d0400+0x0
runtime: found *(0xc0820ae540+0x10) = 0xc0820dc1b8+0xffffffffffffffa8
runtime: found *(0xc082127d18+0x0) = 0xc0820ae540+0x0
fatal error: bad pointer

runtime stack:
runtime.throw(0xabbfb9)
        /usr/local/go/src/runtime/panic.go:491 +0xad fp=0x3df9e8 sp=0x3df9b8
scanblock(0xc082127d18, 0x38, 0x94ca34)
        /usr/local/go/src/runtime/mgc0.c:415 +0x990 fp=0x3dfb28 sp=0x3df9e8
scanframe(0x3dfc30, 0x0, 0x1)
        /usr/local/go/src/runtime/mgc0.c:743 +0x1c9 fp=0x3dfb98 sp=0x3dfb28
runtime.gentraceback(0x418f7c, 0xc082127378, 0x0, 0xc08202c7e0, 0x0, 0x0, 0x7fffffff,
 0x3dfce0, 0x0, 0x0, ...)
        /usr/local/go/src/runtime/traceback.go:311 +0x7af fp=0x3dfc88 sp=0x3dfb98
scanstack(0xc08202c7e0)
        /usr/local/go/src/runtime/mgc0.c:780 +0x22a fp=0x3dfcf8 sp=0x3dfc88
markroot(0xc082010000, 0xc00000000c)
        /usr/local/go/src/runtime/mgc0.c:556 +0xee fp=0x3dfd58 sp=0x3dfcf8
runtime.parfordo(0xc082010000)
        /usr/local/go/src/runtime/parfor.c:76 +0xb9 fp=0x3dfdd8 sp=0x3dfd58
gc(0x3dff10)
        /usr/local/go/src/runtime/mgc0.c:1442 +0x26c fp=0x3dfef0 sp=0x3dfdd8
runtime.gc_m()
        /usr/local/go/src/runtime/mgc0.c:1376 +0x11a fp=0x3dff28 sp=0x3dfef0
runtime.onM(0xc082012000)
        /usr/local/go/src/runtime/asm_amd64.s:257 +0x6d fp=0x3dff30 sp=0x3dff28
runtime.mstart()
        /usr/local/go/src/runtime/proc.c:818 fp=0x3dff38 sp=0x3dff30

goroutine 12 [garbage collection]:
runtime.switchtoM()
        /usr/local/go/src/runtime/asm_amd64.s:198 fp=0xc0821257d0 sp=0xc0821257c8
runtime.gogc(0x0)
        /usr/local/go/src/runtime/malloc.go:469 +0x1d6 fp=0xc082125808 sp=0xc0821257d
0
runtime.mallocgc(0x5000, 0x81d740, 0xc000000001, 0x4b005500000000)
        /usr/local/go/src/runtime/malloc.go:341 +0x398 fp=0xc0821258b8 sp=0xc08212580
8
runtime.newarray(0x81d740, 0x12ed, 0x1c0000)
        /usr/local/go/src/runtime/malloc.go:365 +0xc8 fp=0xc0821258f0 sp=0xc0821258b8

runtime.makeslice(0x7576a0, 0x12ed, 0x12ed, 0x0, 0x0, 0x0)
        /usr/local/go/src/runtime/slice.go:32 +0x163 fp=0xc082125938 sp=0xc0821258f0
github.com/docker/docker/pkg/term/winconsole.clearDisplayRect(0x24, 0x700000020, 0x55
004900540011, 0xc08207004b, 0x5100000001, 0x0, 0x0)
        /go/src/github.com/docker/docker/pkg/term/winconsole/console_windows.go:442 +
0xd8 fp=0xc0821259c8 sp=0xc082125938
github.com/docker/docker/pkg/term/winconsole.clearDisplayRange(0x24, 0x4000700000020,
 0x55004a00540010, 0x4b, 0x0, 0x0, 0x0)
        /go/src/github.com/docker/docker/pkg/term/winconsole/console_windows.go:489 +
0x362 fp=0xc082125a40 sp=0xc0821259c8
github.com/docker/docker/pkg/term/winconsole.(*WindowsTerminal).HandleOutputCommand(0
xc0820b08c0, 0x24, 0xc08207a300, 0x3, 0x100, 0x0, 0x0, 0x0)rings
        /go/src/github.com/docker/docker/pkg/term/winconsole/console_windows.go:799 +
0xdf3 fp=0xc082125c28 sp=0xc082125a40 mount              su
github.com/docker/docker/pkg/term/winconsole.(*terminalWriter).Write(0xc08200ab40, 0x
c082111000, 0x4, 0x1000, 0x1c5, 0x0, 0x0)                swapoff
        /go/src/github.com/docker/docker/pkg/term/winconsole/term_emulator.go:96 +0x3
cf fp=0xc082125d48 sp=0xc082125c28    nameif             switch_root
bufio.(*Reader).writeBuf(0xc0820ee480, 0x1d22d8, 0xc08200ab40, 0x1c5, 0x0, 0x0)
        /usr/local/go/src/bufio/bufio.go:463 +0xac fp=0xc082125db0 sp=0xc082125d48
bufio.(*Reader).WriteTo(0xc0820ee480, 0x1d22d8, 0xc08200ab40, 0x2422, 0x0, 0x0)
        /usr/local/go/src/bufio/bufio.go:444 +0x230 fp=0xc082125e28 sp=0xc082125db0
io.Copy(0x1d22d8, 0xc08200ab40, 0x1d4680, 0xc0820ee480, 0x0, 0x0, 0x0)
        /usr/local/go/src/io/io.go:354 +0xb9 fp=0xc082125ee0 sp=0xc082125e28
github.com/docker/docker/api/client.func┬╖024(0x0, 0x0)  tee
        /go/src/github.com/docker/docker/api/client/hijack.go:210 +0x1e0 fp=0xc082125
fa8 sp=0xc082125ee0ip                 passwd             test
github.com/docker/docker/pkg/promise.func┬╖001()         tftp
        /go/src/github.com/docker/docker/pkg/promise/promise.go:8 +0x36 fp=0xc082125f
e0 sp=0xc082125fa8 ipcs               ping               top
runtime.goexit()   iplink             pipe_progress      touch
        /usr/local/go/src/runtime/asm_amd64.s:2232 +0x1 fp=0xc082125fe8 sp=0xc082125f
e0t                iprule             poweroff           traceroute
created by github.com/docker/docker/pkg/promise.Go       true
        /go/src/github.com/docker/docker/pkg/promise/promise.go:9 +0x102
dd                 iptables-save      ps                 udhcpc
goroutine 1 [chan receive]:-xml       pwd                umount
runtime.gopark(0x439680, 0xc0820ee7d8, 0x8b8650, 0xc)    uname
        /usr/local/go/src/runtime/proc.go:130 +0x10c fp=0xc0820195d8 sp=0xc0820195a8
runtime.goparkunlock(0xc0820ee7d8, 0x8b8650, 0xc)        unix2dos
        /usr/local/go/src/runtime/proc.go:136 +0x4f fp=0xc082019600 sp=0xc0820195d8
runtime.chanrecv(0x75a520, 0xc0820ee780, 0xc082019988, 0x1, 0x0)
        /usr/local/go/src/runtime/chan.go:467 +0x833 fp=0xc0820196a0 sp=0xc082019600
runtime.chanrecv1(0x75a520, 0xc0820ee780, 0xc082019988)  uptime
        /usr/local/go/src/runtime/chan.go:311 +0x2b fp=0xc0820196d0 sp=0xc0820196a0
github.com/docker/docker/api/client.(*DockerCli).CmdRun(0xc0820aca00, 0xc08200a1b0, 0
x3, 0x3, 0x0, 0x0) linux32            rmdir              uuencode
        /go/src/github.com/docker/docker/api/client/commands.go:2476 +0xfc9 fp=0xc082
019af8 sp=0xc0820196d0                route              vi
runtime.call64(0x88cda8, 0xc0820f13b0, 0x2000000030)     vlock
        /usr/local/go/src/runtime/asm_amd64.s:403 +0x4c fp=0xc082019b40 sp=0xc082019a
f8ect              loadkmap           rtacct             watchdog
reflect.callMethod(0xc0820f1350, 0xc082019be8)           wc
        /usr/local/go/src/reflect/value.go:605 +0x180 fp=0xc082019bd0 sp=0xc082019b40
expr               logname            rtstat             which
reflect.methodValueCall(0xc08200a1b0, 0x3, 0x3, 0x1, 0xc0820f1350, 0xc0820aca01, 0xc0
82073290, 0x5, 0xc08200ab00, 0x1c5ee0, ...)vel           whoami
        /usr/local/go/src/reflect/asm_amd64.s:29 +0x3d fp=0xc082019be8 sp=0xc082019bd
0grep              lsmod              seq                xtables-multi
github.com/docker/docker/api/client.(*DockerCli).Cmd(0xc0820aca00, 0xc08200a1a0, 0x4,
 0x4, 0x0, 0x0)    lspci              setconsole         xzcat
        /go/src/github.com/docker/docker/api/client/cli.go:81 +0x385 fp=0xc082019ca8
sp=0xc082019be8    lzcat              setlogcons         zcat
main.main()
        /go/src/github.com/docker/docker/docker/docker.go:138 +0xb90 fp=0xc082019f98
sp=0xc082019ca8
runtime.main()
        /usr/local/go/src/runtime/proc.go:63 +0xfa fp=0xc082019fe0 sp=0xc082019f98
runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:2232 +0x1 fp=0xc082019fe8 sp=0xc082019f
e0

goroutine 2 [force gc (idle)]:
runtime.gopark(0x439680, 0xaca880, 0x8bb0d0, 0xf)
        /usr/local/go/src/runtime/proc.go:130 +0x10c fp=0xc08201df98 sp=0xc08201df68
runtime.goparkunlock(0xaca880, 0x8bb0d0, 0xf)
        /usr/local/go/src/runtime/proc.go:136 +0x4f fp=0xc08201dfc0 sp=0xc08201df98
runtime.forcegchelper()
        /usr/local/go/src/runtime/proc.go:99 +0xd5 fp=0xc08201dfe0 sp=0xc08201dfc0
runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:2232 +0x1 fp=0xc08201dfe8 sp=0xc08201df
e0
created by runtime.init┬╖4
        /usr/local/go/src/runtime/proc.go:87 +0x2c

goroutine 3 [runnable]:
runtime.gopark(0x439680, 0xad7488, 0x8adf50, 0xd)
        /usr/local/go/src/runtime/proc.go:130 +0x10c fp=0xc08201bf98 sp=0xc08201bf68
runtime.goparkunlock(0xad7488, 0x8adf50, 0xd)
        /usr/local/go/src/runtime/proc.go:136 +0x4f fp=0xc08201bfc0 sp=0xc08201bf98
runtime.bgsweep()
        /usr/local/go/src/runtime/mgc0.go:98 +0xc3 fp=0xc08201bfe0 sp=0xc08201bfc0
runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:2232 +0x1 fp=0xc08201bfe8 sp=0xc08201bf
e0
created by gc
        /usr/local/go/src/runtime/mgc0.c:1386

goroutine 4 [finalizer wait]:
runtime.gopark(0x439680, 0xad7480, 0x8ba9d0, 0xe)
        /usr/local/go/src/runtime/proc.go:130 +0x10c fp=0xc08204bf30 sp=0xc08204bf00
runtime.goparkunlock(0xad7480, 0x8ba9d0, 0xe)
        /usr/local/go/src/runtime/proc.go:136 +0x4f fp=0xc08204bf58 sp=0xc08204bf30
runtime.runfinq()
        /usr/local/go/src/runtime/malloc.go:727 +0xc1 fp=0xc08204bfe0 sp=0xc08204bf58

runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:2232 +0x1 fp=0xc08204bfe8 sp=0xc08204bf
e0
created by runtime.createfing
        /usr/local/go/src/runtime/malloc.go:707 +0x65

goroutine 5 [syscall]:
runtime.notetsleepg(0xad84c0, 0xffffffffffffffff, 0xacb601)
        /usr/local/go/src/runtime/lock_sema.go:266 +0x93 fp=0xc08201ff68 sp=0xc08201f
f28
runtime.signal_recv(0x0)
        /usr/local/go/src/runtime/sigqueue.go:109 +0x13c fp=0xc08201ffa0 sp=0xc08201f
f68
os/signal.loop()
        /usr/local/go/src/os/signal/signal_unix.go:21 +0x26 fp=0xc08201ffe0 sp=0xc082
01ffa0
runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:2232 +0x1 fp=0xc08201ffe8 sp=0xc08201ff
e0
created by os/signal.init┬╖1
        /usr/local/go/src/os/signal/signal_unix.go:27 +0x3c

goroutine 11 [chan receive]:
runtime.gopark(0x439680, 0xc0820ee538, 0x8b8650, 0xc)
        /usr/local/go/src/runtime/proc.go:130 +0x10c fp=0xc082045bd0 sp=0xc082045ba0
runtime.goparkunlock(0xc0820ee538, 0x8b8650, 0xc)
        /usr/local/go/src/runtime/proc.go:136 +0x4f fp=0xc082045bf8 sp=0xc082045bd0
runtime.chanrecv(0x75a520, 0xc0820ee4e0, 0xc082045e30, 0xc082042001, 0xc082040000)
        /usr/local/go/src/runtime/chan.go:467 +0x833 fp=0xc082045c98 sp=0xc082045bf8
runtime.chanrecv1(0x75a520, 0xc0820ee4e0, 0xc082045e30)
        /usr/local/go/src/runtime/chan.go:311 +0x2b fp=0xc082045cc8 sp=0xc082045c98
github.com/docker/docker/api/client.(*DockerCli).hijack(0xc0820aca00, 0x897c10, 0x4,
0xc0820d0500, 0x76, 0x1, 0x1d2330, 0xc08200abe0, 0x1d22d8, 0xc08200ab40, ...)
        /go/src/github.com/docker/docker/api/client/hijack.go:237 +0xd38 fp=0xc082045
ed0 sp=0xc082045cc8
github.com/docker/docker/api/client.func┬╖015(0x0, 0x0)
        /go/src/github.com/docker/docker/api/client/commands.go:2444 +0x1c9 fp=0xc082
045fa8 sp=0xc082045ed0
github.com/docker/docker/pkg/promise.func┬╖001()
        /go/src/github.com/docker/docker/pkg/promise/promise.go:8 +0x36 fp=0xc082045f
e0 sp=0xc082045fa8
runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:2232 +0x1 fp=0xc082045fe8 sp=0xc082045f
e0
created by github.com/docker/docker/pkg/promise.Go
        /go/src/github.com/docker/docker/pkg/promise/promise.go:9 +0x102

goroutine 7 [syscall]:
runtime.notetsleepg(0xacaa58, 0x7732bae60, 0x5)
        /usr/local/go/src/runtime/lock_sema.go:266 +0x93 fp=0xc082049f68 sp=0xc082049
f28
runtime.timerproc()
        /usr/local/go/src/runtime/time.go:207 +0x101 fp=0xc082049fe0 sp=0xc082049f68
runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:2232 +0x1 fp=0xc082049fe8 sp=0xc082049f
e0
created by runtime.addtimerLocked
        /usr/local/go/src/runtime/time.go:113 +0x1c1

goroutine 9 [IO wait]:
runtime.gopark(0x4157a0, 0x1d3c40, 0x895bb0, 0x7)
        /usr/local/go/src/runtime/proc.go:130 +0x10c fp=0xc0821273a8 sp=0xc082127378
runtime.netpollblock(0x1d3c18, 0x72, 0xc082066001)
        /usr/local/go/src/runtime/netpoll.go:347 +0x177 fp=0xc0821273e8 sp=0xc0821273
a8
runtime.netpollWait(0x1d3c18, 0x72, 0xc0820cf448)
        /usr/local/go/src/runtime/netpoll.go:150 +0x6f fp=0xc082127408 sp=0xc0821273e
8
net.(*pollDesc).Wait(0xc082066170, 0x72, 0x0, 0x0)
        /usr/local/go/src/net/fd_poll_runtime.go:84 +0x4e fp=0xc082127428 sp=0xc08212
7408
net.(*ioSrv).ExecIO(0xc082042220, 0xc082066060, 0x89a470, 0x7, 0x97bec0, 0x5d, 0x0, 0
x0)
        /usr/local/go/src/net/fd_windows.go:188 +0x305 fp=0xc082127510 sp=0xc08212742
8
net.(*netFD).Read(0xc082066000, 0xc082057400, 0x400, 0x400, 0x0, 0x0, 0x0)
        /usr/local/go/src/net/fd_windows.go:470 +0x180 fp=0xc082127598 sp=0xc08212751
0
net.(*conn).Read(0xc082042238, 0xc082057400, 0x400, 0x400, 0x0, 0x0, 0x0)
        /usr/local/go/src/net/net.go:121 +0xe3 fp=0xc0821275e0 sp=0xc082127598
crypto/tls.(*block).readFromUntil(0xc0820f0780, 0x1d3cd8, 0xc082042238, 0x5, 0x0, 0x0
)
        /usr/local/go/src/crypto/tls/conn.go:454 +0xed fp=0xc082127648 sp=0xc0821275e
0
crypto/tls.(*Conn).readRecord(0xc082086580, 0x17, 0x0, 0x0)
        /usr/local/go/src/crypto/tls/conn.go:539 +0x2e1 fp=0xc082127b90 sp=0xc0821276
48
crypto/tls.(*Conn).Read(0xc082086580, 0xc08200f000, 0x1000, 0x1000, 0x0, 0x0, 0x0)
        /usr/local/go/src/crypto/tls/conn.go:904 +0x16d fp=0xc082127c78 sp=0xc082127b
90
net/http.noteEOFReader.Read(0x1d4440, 0xc082086580, 0xc0820dc1b8, 0xc08200f000, 0x100
0, 0x1000, 0xc0820d8140, 0x0, 0x0)
        /usr/local/go/src/net/http/transport.go:1270 +0x75 fp=0xc082127cc8 sp=0xc0821
27c78
net/http.(*noteEOFReader).Read(0xc0820ae540, 0xc08200f000, 0x1000, 0x1000, 0xc0820120
00, 0x0, 0x0)
        <autogenerated>:125 +0xdb fp=0xc082127d18 sp=0xc082127cc8
bufio.(*Reader).fill(0xc0820ee600)
        /usr/local/go/src/bufio/bufio.go:97 +0x1d5 fp=0xc082127dc0 sp=0xc082127d18
bufio.(*Reader).Peek(0xc0820ee600, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0)
        /usr/local/go/src/bufio/bufio.go:132 +0xf7 fp=0xc082127dd0 sp=0xc082127dc0
net/http.(*persistConn).readLoop(0xc0820dc160)
        /usr/local/go/src/net/http/transport.go:842 +0xab fp=0xc082127fd8 sp=0xc08212
7dd0
runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:2232 +0x1 fp=0xc082127fe0 sp=0xc082127f
d8
created by net/http.(*Transport).dialConn
        /usr/local/go/src/net/http/transport.go:660 +0xca6

goroutine 10 [select]:
runtime.gopark(0x41a1e0, 0xc082047f40, 0x8a35b0, 0x6)
        /usr/local/go/src/runtime/proc.go:130 +0x10c fp=0xc082047cb8 sp=0xc082047c88
runtime.selectgoImpl(0xc082047f40, 0x0, 0x18)
        /usr/local/go/src/runtime/select.go:366 +0xb33 fp=0xc082047e50 sp=0xc082047cb
8
runtime.selectgo(0xc082047f40)
        /usr/local/go/src/runtime/select.go:183 +0x12 fp=0xc082047e70 sp=0xc082047e50

net/http.(*persistConn).writeLoop(0xc0820dc160)
        /usr/local/go/src/net/http/transport.go:945 +0x424 fp=0xc082047fd8 sp=0xc0820
47e70
runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:2232 +0x1 fp=0xc082047fe0 sp=0xc082047f
d8
created by net/http.(*Transport).dialConn
        /usr/local/go/src/net/http/transport.go:661 +0xcc3

goroutine 13 [runnable, locked to thread]:
runtime.cgocall_errno(0x443e30, 0xc082129ab8, 0x0)
        /usr/local/go/src/runtime/cgocall.go:130 +0xdb fp=0xc082129aa0 sp=0xc082129a7
8
runtime.syscall_Syscall6(0x7ff8627a6940, 0x4, 0x20, 0xc08216b000, 0x400, 0xc08207ed60
, 0x0, 0x0, 0xc08212afc0, 0x411329, ...)
        /usr/local/go/src/runtime/syscall_windows.go:142 +0x6c fp=0xc082129b00 sp=0xc
082129aa0
syscall.(*Proc).Call(0xc0820de020, 0xc082129c68, 0x4, 0x4, 0x10, 0x768720, 0x0, 0x0)
        /usr/local/go/src/syscall/dll_windows.go:136 +0x5c2 fp=0xc082129be0 sp=0xc082
129b00
syscall.(*LazyProc).Call(0xc08205a2d0, 0xc082129c68, 0x4, 0x4, 0xc08216b000, 0x408018
, 0x0, 0x0)
        /usr/local/go/src/syscall/dll_windows.go:279 +0x74 fp=0xc082129c28 sp=0xc0821
29be0
github.com/docker/docker/pkg/term/winconsole.readConsoleInputKey(0x20, 0xc08216b000,
0x400, 0x400, 0x400, 0x0, 0x0)
        /go/src/github.com/docker/docker/pkg/term/winconsole/console_windows.go:554 +
0xf4 fp=0xc082129cb0 sp=0xc082129c28
github.com/docker/docker/pkg/term/winconsole.getAvailableInputEvents(0x20, 0x0, 0x0,
0x0, 0x0, 0x0)
        /go/src/github.com/docker/docker/pkg/term/winconsole/console_windows.go:1060
+0xf1 fp=0xc082129d28 sp=0xc082129cb0
github.com/docker/docker/pkg/term/winconsole.(*WindowsTerminal).ReadChars(0xc0820b08c
0, 0x20, 0x1d23b0, 0xc082042000, 0xc08212c000, 0x8000, 0x8000, 0x0, 0x0, 0x0)
        /go/src/github.com/docker/docker/pkg/term/winconsole/console_windows.go:1101
+0x14b fp=0xc082129dd0 sp=0xc082129d28
github.com/docker/docker/pkg/term/winconsole.(*terminalReader).Read(0xc08200abe0, 0xc
08212c000, 0x8000, 0x8000, 0x1, 0x0, 0x0)
        /go/src/github.com/docker/docker/pkg/term/winconsole/term_emulator.go:153 +0x
14f fp=0xc082129e38 sp=0xc082129dd0
io.Copy(0x1d4a08, 0xc0820de340, 0x1d4b28, 0xc08200abe0, 0x32, 0x0, 0x0)
        /usr/local/go/src/io/io.go:362 +0x1fd fp=0xc082129ef0 sp=0xc082129e38
github.com/docker/docker/api/client.func┬╖025(0x0, 0x0)
        /go/src/github.com/docker/docker/api/client/hijack.go:221 +0xe3 fp=0xc082129f
a8 sp=0xc082129ef0
github.com/docker/docker/pkg/promise.func┬╖001()
        /go/src/github.com/docker/docker/pkg/promise/promise.go:8 +0x36 fp=0xc082129f
e0 sp=0xc082129fa8
runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:2232 +0x1 fp=0xc082129fe8 sp=0xc082129f
e0
created by github.com/docker/docker/pkg/promise.Go
        /go/src/github.com/docker/docker/pkg/promise/promise.go:9 +0x102

width := toCoord.X - fromCoord.X + 1
height := toCoord.Y - fromCoord.Y + 1
size := width * height
if size > 0 {
Copy link
Contributor Author

@sachin-jayant-joshi sachin-jayant-joshi Mar 19, 2015

Thanks
the stack trace shows following line is at the top of the stack. The garbage collector+ memory manager in go is throwing exception.
This is the second time I am seeing GC throwing exceptions . I can eliminate the memory alloc all together by using the static var .
But then it defeats the purpose of having garbage collected language.

@tiborvass
Copy link
Collaborator

@tiborvass tiborvass commented Mar 20, 2015

I have some other stacktraces here: https://gist.github.com/tiborvass/d5f9a64be665fa4e9f38

@sachin-jayant-joshi if you could update this branch with your branch named win-tty-no-chan, that'd be fantastic.

Otherwise we'll have to carry it.

@tiborvass
Copy link
Collaborator

@tiborvass tiborvass commented Mar 22, 2015

Carried at #11566

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

10 participants