Merge pull request #7517 from hashicorp/fix_7506
fix tty related panics
This commit is contained in:
commit
e6363a1bdf
2
go.mod
2
go.mod
|
@ -68,7 +68,7 @@ require (
|
|||
github.com/masterzen/azure-sdk-for-go v0.0.0-20161014135628-ee4f0065d00c // indirect
|
||||
github.com/masterzen/simplexml v0.0.0-20190410153822-31eea3082786 // indirect
|
||||
github.com/masterzen/winrm v0.0.0-20180224160350-7e40f93ae939
|
||||
github.com/mattn/go-tty v0.0.0-20190407112021-83fae09cc007
|
||||
github.com/mattn/go-tty v0.0.0-20190424173100-523744f04859
|
||||
github.com/miekg/dns v1.1.1 // indirect
|
||||
github.com/mitchellh/cli v1.0.0
|
||||
github.com/mitchellh/go-fs v0.0.0-20180402234041-7b48fa161ea7
|
||||
|
|
4
go.sum
4
go.sum
|
@ -260,8 +260,8 @@ github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs
|
|||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
|
||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-tty v0.0.0-20190407112021-83fae09cc007 h1:xjZxmVDmDZoEsl2gV0qD0pyBH+wXmJIZd27wsNFphJk=
|
||||
github.com/mattn/go-tty v0.0.0-20190407112021-83fae09cc007/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE=
|
||||
github.com/mattn/go-tty v0.0.0-20190424173100-523744f04859 h1:smQbSzmT3EHl4EUwtFwFGmGIpiYgIiiPeVv1uguIQEE=
|
||||
github.com/mattn/go-tty v0.0.0-20190424173100-523744f04859/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
|
|
22
main.go
22
main.go
|
@ -186,21 +186,19 @@ func wrappedMain() int {
|
|||
return 1
|
||||
}
|
||||
} else {
|
||||
var TTY packer.TTY
|
||||
if !inPlugin {
|
||||
var err error
|
||||
TTY, err = tty.Open()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "No tty available: %s\n", err)
|
||||
} else {
|
||||
defer TTY.Close()
|
||||
}
|
||||
}
|
||||
ui = &packer.BasicUi{
|
||||
basicUi := &packer.BasicUi{
|
||||
Reader: os.Stdin,
|
||||
Writer: os.Stdout,
|
||||
ErrorWriter: os.Stdout,
|
||||
TTY: TTY,
|
||||
}
|
||||
ui = basicUi
|
||||
if !inPlugin {
|
||||
if TTY, err := tty.Open(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "No tty available: %s\n", err)
|
||||
} else {
|
||||
basicUi.TTY = TTY
|
||||
defer TTY.Close()
|
||||
}
|
||||
}
|
||||
}
|
||||
// Create the CLI meta
|
||||
|
|
|
@ -38,6 +38,10 @@ func (tty *TTY) Size() (int, int, error) {
|
|||
return tty.size()
|
||||
}
|
||||
|
||||
func (tty *TTY) SizePixel() (int, int, int, int, error) {
|
||||
return tty.sizePixel()
|
||||
}
|
||||
|
||||
func (tty *TTY) Input() *os.File {
|
||||
return tty.input()
|
||||
}
|
||||
|
@ -115,6 +119,6 @@ type WINSIZE struct {
|
|||
H int
|
||||
}
|
||||
|
||||
func (tty *TTY) SIGWINCH() chan WINSIZE {
|
||||
func (tty *TTY) SIGWINCH() <-chan WINSIZE {
|
||||
return tty.sigwinch()
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"bufio"
|
||||
"os"
|
||||
"syscall"
|
||||
"errors"
|
||||
)
|
||||
|
||||
type TTY struct {
|
||||
|
@ -54,6 +55,11 @@ func (tty *TTY) size() (int, int, error) {
|
|||
return 80, 24, nil
|
||||
}
|
||||
|
||||
func (tty *TTY) sizePixel() (int, int, int, int, error) {
|
||||
x, y, _ := tty.size()
|
||||
return x, y, -1, -1, errors.New("no implemented method for querying size in pixels on Plan 9")
|
||||
}
|
||||
|
||||
func (tty *TTY) input() *os.File {
|
||||
return tty.in
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ type TTY struct {
|
|||
bin *bufio.Reader
|
||||
out *os.File
|
||||
termios syscall.Termios
|
||||
ws chan WINSIZE
|
||||
ss chan os.Signal
|
||||
}
|
||||
|
||||
|
@ -48,24 +47,8 @@ func open() (*TTY, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
tty.ws = make(chan WINSIZE)
|
||||
tty.ss = make(chan os.Signal, 1)
|
||||
signal.Notify(tty.ss, syscall.SIGWINCH)
|
||||
go func() {
|
||||
defer close(tty.ws)
|
||||
for sig := range tty.ss {
|
||||
switch sig {
|
||||
case syscall.SIGWINCH:
|
||||
if w, h, err := tty.size(); err == nil {
|
||||
tty.ws <- WINSIZE{
|
||||
W: w,
|
||||
H: h,
|
||||
}
|
||||
}
|
||||
default:
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return tty, nil
|
||||
}
|
||||
|
||||
|
@ -86,11 +69,16 @@ func (tty *TTY) close() error {
|
|||
}
|
||||
|
||||
func (tty *TTY) size() (int, int, error) {
|
||||
x, y, _, _, err := tty.sizePixel()
|
||||
return x, y, err
|
||||
}
|
||||
|
||||
func (tty *TTY) sizePixel() (int, int, int, int, error) {
|
||||
var dim [4]uint16
|
||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(tty.out.Fd()), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&dim)), 0, 0, 0); err != 0 {
|
||||
return -1, -1, err
|
||||
return -1, -1, -1, -1, err
|
||||
}
|
||||
return int(dim[1]), int(dim[0]), nil
|
||||
return int(dim[1]), int(dim[0]), int(dim[2]), int(dim[3]), nil
|
||||
}
|
||||
|
||||
func (tty *TTY) input() *os.File {
|
||||
|
@ -127,6 +115,28 @@ func (tty *TTY) raw() (func() error, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (tty *TTY) sigwinch() chan WINSIZE {
|
||||
return tty.ws
|
||||
func (tty *TTY) sigwinch() <-chan WINSIZE {
|
||||
signal.Notify(tty.ss, syscall.SIGWINCH)
|
||||
|
||||
ws := make(chan WINSIZE)
|
||||
go func() {
|
||||
defer close(ws)
|
||||
for sig := range tty.ss {
|
||||
if sig != syscall.SIGWINCH {
|
||||
continue
|
||||
}
|
||||
|
||||
w, h, err := tty.size()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
// send but do not block for it
|
||||
select {
|
||||
case ws <- WINSIZE{W: w, H: h}:
|
||||
default:
|
||||
}
|
||||
|
||||
}
|
||||
}()
|
||||
return ws
|
||||
}
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
package tty
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"errors"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
|
@ -122,11 +124,13 @@ type charInfo struct {
|
|||
}
|
||||
|
||||
type TTY struct {
|
||||
in *os.File
|
||||
out *os.File
|
||||
st uint32
|
||||
rs []rune
|
||||
ws chan WINSIZE
|
||||
in *os.File
|
||||
out *os.File
|
||||
st uint32
|
||||
rs []rune
|
||||
ws chan WINSIZE
|
||||
sigwinchCtx context.Context
|
||||
sigwinchCtxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
func readConsoleInput(fd uintptr, record *inputRecord) (err error) {
|
||||
|
@ -183,6 +187,7 @@ func open() (*TTY, error) {
|
|||
procSetConsoleMode.Call(h, uintptr(st))
|
||||
|
||||
tty.ws = make(chan WINSIZE)
|
||||
tty.sigwinchCtx, tty.sigwinchCtxCancel = context.WithCancel(context.Background())
|
||||
|
||||
return tty, nil
|
||||
}
|
||||
|
@ -206,10 +211,24 @@ func (tty *TTY) readRune() (rune, error) {
|
|||
switch ir.eventType {
|
||||
case windowBufferSizeEvent:
|
||||
wr := (*windowBufferSizeRecord)(unsafe.Pointer(&ir.event))
|
||||
tty.ws <- WINSIZE{
|
||||
ws := WINSIZE{
|
||||
W: int(wr.size.x),
|
||||
H: int(wr.size.y),
|
||||
}
|
||||
|
||||
if err := tty.sigwinchCtx.Err(); err != nil {
|
||||
// closing
|
||||
// the following select might panic without this guard close
|
||||
return 0, err
|
||||
}
|
||||
|
||||
select {
|
||||
case tty.ws <- ws:
|
||||
case <-tty.sigwinchCtx.Done():
|
||||
return 0, tty.sigwinchCtx.Err()
|
||||
default:
|
||||
return 0, nil // no one is currently trying to read
|
||||
}
|
||||
case keyEvent:
|
||||
kr := (*keyEventRecord)(unsafe.Pointer(&ir.event))
|
||||
if kr.keyDown != 0 {
|
||||
|
@ -307,8 +326,9 @@ func (tty *TTY) readRune() (rune, error) {
|
|||
}
|
||||
|
||||
func (tty *TTY) close() error {
|
||||
close(tty.ws)
|
||||
procSetConsoleMode.Call(tty.in.Fd(), uintptr(tty.st))
|
||||
tty.sigwinchCtxCancel()
|
||||
close(tty.ws)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -321,6 +341,15 @@ func (tty *TTY) size() (int, int, error) {
|
|||
return int(csbi.window.right - csbi.window.left + 1), int(csbi.window.bottom - csbi.window.top + 1), nil
|
||||
}
|
||||
|
||||
func (tty *TTY) sizePixel() (int, int, int, int, error) {
|
||||
x, y, err := tty.size()
|
||||
if err != nil {
|
||||
x = -1
|
||||
y = -1
|
||||
}
|
||||
return x, y, -1, -1, errors.New("no implemented method for querying size in pixels on Windows")
|
||||
}
|
||||
|
||||
func (tty *TTY) input() *os.File {
|
||||
return tty.in
|
||||
}
|
||||
|
@ -349,6 +378,6 @@ func (tty *TTY) raw() (func() error, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (tty *TTY) sigwinch() chan WINSIZE {
|
||||
func (tty *TTY) sigwinch() <-chan WINSIZE {
|
||||
return tty.ws
|
||||
}
|
||||
|
|
|
@ -317,7 +317,7 @@ github.com/mattn/go-colorable
|
|||
github.com/mattn/go-isatty
|
||||
# github.com/mattn/go-runewidth v0.0.4
|
||||
github.com/mattn/go-runewidth
|
||||
# github.com/mattn/go-tty v0.0.0-20190407112021-83fae09cc007
|
||||
# github.com/mattn/go-tty v0.0.0-20190424173100-523744f04859
|
||||
github.com/mattn/go-tty
|
||||
# github.com/mitchellh/cli v1.0.0
|
||||
github.com/mitchellh/cli
|
||||
|
|
Loading…
Reference in New Issue