containerd/console

console.NewPty panics on macOS

slonopotamus opened this issue · 2 comments

macOS Ventura, M1, go 1.20.6, console 1.0.3

A trivial program

package main

import "github.com/containerd/console"

func main() {
	_, _, _ = console.NewPty()
}

Crashes with

% go run cmd/main.go 
runtime: g 1: unexpected return pc for runtime.sigpanic called from 0x0
stack: frame={sp:0x14000070f10, fp:0x14000070f50} stack=[0x14000070000,0x14000071000)
0x0000014000070e10:  0x0000014000070ef0  0x00000140000021a0 
0x0000014000070e20:  0x0000000000000000  0x0000014000070ee8 
0x0000014000070e30:  0x0000000102b2dae8 <runtime.panicmem+0x0000000000000048>  0x0000000020007452 
0x0000014000070e40:  0x0000014000070f04  0xffffffffffffffff 
0x0000014000070e50:  0xffffffffffffffff  0x0000000000000009 
0x0000014000070e60:  0x0000000102b8d210 <libc_ioctl_trampoline+0x0000000000000000>  0x0000014000070e98 
0x0000014000070e70:  0x0000000102b8cf40 <golang.org/x/sys/unix.ioctlPtr+0x00000000000000a0>  0x00000140000021a0 
0x0000014000070e80:  0x0000000000000000  0x0000000000000000 
0x0000014000070e90:  0x0000000000000000  0x0000014000070ed8 
0x0000014000070ea0:  0x0000000102b8d710 <github.com/containerd/console.unlockpt+0x0000000000000060>  0x00000140000021c0 
0x0000014000070eb0:  0x0000000000000000  0x0000000102bbaf40 
0x0000014000070ec0:  0x0000000102c412e0  0x0000000000000000 
0x0000014000070ed0:  0x0000000000000000  0x0000000000000000 
0x0000014000070ee0:  0x0000000000000000  0x0000014000070f08 
0x0000014000070ef0:  0x0000000102b44b38 <runtime.sigpanic+0x0000000000000218>  0x0000000102bbaf40 
0x0000014000070f00:  0x0000000102c412e0  0x0000000000000000 
0x0000014000070f10: <0x0000000000000000  0x0000000000000000 
0x0000014000070f20:  0x0000000000000000  0x0000000000000000 
0x0000014000070f30:  0x0000000000000000  0x0000000000000000 
0x0000014000070f40:  0x00000140000021a0  0x0000000000000000 
0x0000014000070f50: >0x0000000000000000  0x0000000000000000 
0x0000014000070f60:  0x0000000000000000  0x0000000000000000 
0x0000014000070f70:  0x0000000102b5cb54 <runtime.goexit+0x0000000000000004>  0x000001400006a000 
0x0000014000070f80:  0x0000000000000000  0x0000000000000000 
0x0000014000070f90:  0x0000000000000000  0x0100000000000000 
0x0000014000070fa0:  0x0000000000000000  0x0000000102c48c40 
0x0000014000070fb0:  0x0000000102b31c30 <runtime.main.func2+0x0000000000000000>  0x0000014000070f9e 
0x0000014000070fc0:  0x0000014000070fb0  0x0000000000000000 
0x0000014000070fd0:  0x0000000000000000  0x0000000000000000 
0x0000014000070fe0:  0x0000000000000000  0x0000000000000000 
0x0000014000070ff0:  0x0000000000000000  0x0000000000000000 
fatal error: unknown caller pc

runtime stack:
runtime.throw({0x102b8ff13?, 0x102c36060?})
        /opt/homebrew/opt/go/libexec/src/runtime/panic.go:1047 +0x40 fp=0x16d2ff040 sp=0x16d2ff010 pc=0x102b2f4b0
runtime.gentraceback(0x102d98000?, 0x16d2ff3d0?, 0x2b370001873cc434?, 0x140000021a0, 0x0, 0x0, 0x7fffffff, 0x16d2ff410, 0x8124800102b5e12c?, 0x0)
        /opt/homebrew/opt/go/libexec/src/runtime/traceback.go:270 +0x14bc fp=0x16d2ff3b0 sp=0x16d2ff040 pc=0x102b529ac
runtime.addOneOpenDeferFrame.func1()
        /opt/homebrew/opt/go/libexec/src/runtime/panic.go:645 +0x64 fp=0x16d2ff430 sp=0x16d2ff3b0 pc=0x102b2e6c4
runtime.systemstack()
        /opt/homebrew/opt/go/libexec/src/runtime/asm_arm64.s:243 +0x6c fp=0x16d2ff440 sp=0x16d2ff430 pc=0x102b5a70c

goroutine 1 [running]:
runtime.systemstack_switch()
        /opt/homebrew/opt/go/libexec/src/runtime/asm_arm64.s:200 +0x8 fp=0x14000070df0 sp=0x14000070de0 pc=0x102b5a688
runtime.addOneOpenDeferFrame(0x20007452?, 0x14000070f04?, 0xffffffffffffffff?)
        /opt/homebrew/opt/go/libexec/src/runtime/panic.go:644 +0x64 fp=0x14000070e30 sp=0x14000070df0 pc=0x102b2e624
panic({0x102bbaf40, 0x102c412e0})
        /opt/homebrew/opt/go/libexec/src/runtime/panic.go:844 +0xf4 fp=0x14000070ef0 sp=0x14000070e30 pc=0x102b2ee54
runtime.panicmem()
        /opt/homebrew/opt/go/libexec/src/runtime/panic.go:260 +0x48 fp=0x14000070f10 sp=0x14000070ef0 pc=0x102b2dae8
runtime: g 1: unexpected return pc for runtime.sigpanic called from 0x0
stack: frame={sp:0x14000070f10, fp:0x14000070f50} stack=[0x14000070000,0x14000071000)
0x0000014000070e10:  0x0000014000070ef0  0x00000140000021a0 
0x0000014000070e20:  0x0000000000000000  0x0000014000070ee8 
0x0000014000070e30:  0x0000000102b2dae8 <runtime.panicmem+0x0000000000000048>  0x0000000020007452 
0x0000014000070e40:  0x0000014000070f04  0xffffffffffffffff 
0x0000014000070e50:  0xffffffffffffffff  0x0000000000000009 
0x0000014000070e60:  0x0000000102b8d210 <libc_ioctl_trampoline+0x0000000000000000>  0x0000014000070e98 
0x0000014000070e70:  0x0000000102b8cf40 <golang.org/x/sys/unix.ioctlPtr+0x00000000000000a0>  0x00000140000021a0 
0x0000014000070e80:  0x0000000000000000  0x0000000000000000 
0x0000014000070e90:  0x0000000000000000  0x0000014000070ed8 
0x0000014000070ea0:  0x0000000102b8d710 <github.com/containerd/console.unlockpt+0x0000000000000060>  0x00000140000021c0 
0x0000014000070eb0:  0x0000000000000000  0x0000000102bbaf40 
0x0000014000070ec0:  0x0000000102c412e0  0x0000000000000000 
0x0000014000070ed0:  0x0000000000000000  0x0000000000000000 
0x0000014000070ee0:  0x0000000000000000  0x0000014000070f08 
0x0000014000070ef0:  0x0000000102b44b38 <runtime.sigpanic+0x0000000000000218>  0x0000000102bbaf40 
0x0000014000070f00:  0x0000000102c412e0  0x0000000000000000 
0x0000014000070f10: <0x0000000000000000  0x0000000000000000 
0x0000014000070f20:  0x0000000000000000  0x0000000000000000 
0x0000014000070f30:  0x0000000000000000  0x0000000000000000 
0x0000014000070f40:  0x00000140000021a0  0x0000000000000000 
0x0000014000070f50: >0x0000000000000000  0x0000000000000000 
0x0000014000070f60:  0x0000000000000000  0x0000000000000000 
0x0000014000070f70:  0x0000000102b5cb54 <runtime.goexit+0x0000000000000004>  0x000001400006a000 
0x0000014000070f80:  0x0000000000000000  0x0000000000000000 
0x0000014000070f90:  0x0000000000000000  0x0100000000000000 
0x0000014000070fa0:  0x0000000000000000  0x0000000102c48c40 
0x0000014000070fb0:  0x0000000102b31c30 <runtime.main.func2+0x0000000000000000>  0x0000014000070f9e 
0x0000014000070fc0:  0x0000014000070fb0  0x0000000000000000 
0x0000014000070fd0:  0x0000000000000000  0x0000000000000000 
0x0000014000070fe0:  0x0000000000000000  0x0000000000000000 
0x0000014000070ff0:  0x0000000000000000  0x0000000000000000 
runtime.sigpanic()
        /opt/homebrew/opt/go/libexec/src/runtime/signal_unix.go:841 +0x218 fp=0x14000070f50 sp=0x14000070f10 pc=0x102b44b38

goroutine 2 [force gc (idle)]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
        /opt/homebrew/opt/go/libexec/src/runtime/proc.go:381 +0xe4 fp=0x14000044fa0 sp=0x14000044f80 pc=0x102b31f24
runtime.goparkunlock(...)
        /opt/homebrew/opt/go/libexec/src/runtime/proc.go:387
runtime.forcegchelper()
        /opt/homebrew/opt/go/libexec/src/runtime/proc.go:305 +0xb8 fp=0x14000044fd0 sp=0x14000044fa0 pc=0x102b31d68
runtime.goexit()
        /opt/homebrew/opt/go/libexec/src/runtime/asm_arm64.s:1172 +0x4 fp=0x14000044fd0 sp=0x14000044fd0 pc=0x102b5cb54
created by runtime.init.6
        /opt/homebrew/opt/go/libexec/src/runtime/proc.go:293 +0x24

goroutine 3 [GC sweep wait]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
        /opt/homebrew/opt/go/libexec/src/runtime/proc.go:381 +0xe4 fp=0x14000045760 sp=0x14000045740 pc=0x102b31f24
runtime.goparkunlock(...)
        /opt/homebrew/opt/go/libexec/src/runtime/proc.go:387
runtime.bgsweep(0x0?)
        /opt/homebrew/opt/go/libexec/src/runtime/mgcsweep.go:278 +0xa4 fp=0x140000457b0 sp=0x14000045760 pc=0x102b1fb54
runtime.gcenable.func1()
        /opt/homebrew/opt/go/libexec/src/runtime/mgc.go:178 +0x28 fp=0x140000457d0 sp=0x140000457b0 pc=0x102b14908
runtime.goexit()
        /opt/homebrew/opt/go/libexec/src/runtime/asm_arm64.s:1172 +0x4 fp=0x140000457d0 sp=0x140000457d0 pc=0x102b5cb54
created by runtime.gcenable
        /opt/homebrew/opt/go/libexec/src/runtime/mgc.go:178 +0x74

goroutine 4 [GC scavenge wait]:
runtime.gopark(0x1400005a000?, 0x102babf88?, 0x1?, 0x0?, 0x0?)
        /opt/homebrew/opt/go/libexec/src/runtime/proc.go:381 +0xe4 fp=0x14000045f50 sp=0x14000045f30 pc=0x102b31f24
runtime.goparkunlock(...)
        /opt/homebrew/opt/go/libexec/src/runtime/proc.go:387
runtime.(*scavengerState).park(0x102c487c0)
        /opt/homebrew/opt/go/libexec/src/runtime/mgcscavenge.go:400 +0x5c fp=0x14000045f80 sp=0x14000045f50 pc=0x102b1d9dc
runtime.bgscavenge(0x0?)
        /opt/homebrew/opt/go/libexec/src/runtime/mgcscavenge.go:628 +0x44 fp=0x14000045fb0 sp=0x14000045f80 pc=0x102b1df54
runtime.gcenable.func2()
        /opt/homebrew/opt/go/libexec/src/runtime/mgc.go:179 +0x28 fp=0x14000045fd0 sp=0x14000045fb0 pc=0x102b148a8
runtime.goexit()
        /opt/homebrew/opt/go/libexec/src/runtime/asm_arm64.s:1172 +0x4 fp=0x14000045fd0 sp=0x14000045fd0 pc=0x102b5cb54
created by runtime.gcenable
        /opt/homebrew/opt/go/libexec/src/runtime/mgc.go:179 +0xb8

goroutine 5 [finalizer wait]:
runtime.gopark(0x140000445a8?, 0x60000102b127f8?, 0x48?, 0x6a?, 0x1?)
        /opt/homebrew/opt/go/libexec/src/runtime/proc.go:381 +0xe4 fp=0x14000044580 sp=0x14000044560 pc=0x102b31f24
runtime.runfinq()
        /opt/homebrew/opt/go/libexec/src/runtime/mfinal.go:193 +0x10c fp=0x140000447d0 sp=0x14000044580 pc=0x102b1399c
runtime.goexit()
        /opt/homebrew/opt/go/libexec/src/runtime/asm_arm64.s:1172 +0x4 fp=0x140000447d0 sp=0x140000447d0 pc=0x102b5cb54
created by runtime.createfing
        /opt/homebrew/opt/go/libexec/src/runtime/mfinal.go:163 +0x84
exit status 2

And the reason for the crash is that ptsname in tc_darwin.go is totally broken.

First, it attempts to use %d to print a 64-bit value.

Second, and most important, it doesn't properly use syscall.TIOCPTYGNAME. It is supposed to be called something like this:

func ptsname(f *os.File) (string, error) {
	n := make([]byte, 128)
	if _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, f.Fd(), syscall.TIOCPTYGNAME, uintptr(unsafe.Pointer(&n[0]))); errno != 0 {
		return "", errno
	}

	end := bytes.IndexByte(n, 0)
	if end < 0 {
		return "", errors.New("TIOCPTYGNAME string not NUL-terminated")
	}

	return string(n[:end]), nil
}

@dmcgowan can we merge this?