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

runtime: freedefer with d._panic != nil (regression in 1.13) #33841

Closed
josharian opened this issue Aug 26, 2019 · 8 comments
Closed

runtime: freedefer with d._panic != nil (regression in 1.13) #33841

josharian opened this issue Aug 26, 2019 · 8 comments
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. release-blocker
Milestone

Comments

@josharian
Copy link
Contributor

This is a regression from 1.12 to 1.13rc1. I'm on darwin/amd64.

main.go (this is just the demo code from https://github.com/awesome-gocui/gocui):

package main

import (
	"fmt"
	"log"

	"github.com/awesome-gocui/gocui"
)

func main() {
	g, err := gocui.NewGui(gocui.OutputNormal, false)
	if err != nil {
		log.Panicln(err)
	}
	defer g.Close()

	g.SetManagerFunc(layout)

	if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
		log.Panicln(err)
	}

	if err := g.MainLoop(); err != nil && !gocui.IsQuit(err) {
		log.Panicln(err)
	}
}

func layout(g *gocui.Gui) error {
	maxX, maxY := g.Size()
	if v, err := g.SetView("hello", maxX/2-7, maxY/2, maxX/2+7, maxY/2+2, 0); err != nil {
		if !gocui.IsUnknownView(err) {
			return err
		}
		fmt.Fprintln(v, "Hello world!")
		if _, err := g.SetCurrentView("hello"); err != nil {
			return err
		}
	}
	return nil
}

func quit(g *gocui.Gui, v *gocui.View) error {
	return gocui.ErrQuit
}

go.mod:

module bug

go 1.13

require github.com/awesome-gocui/gocui v0.5.0

go.sum (just in case):

github.com/awesome-gocui/gocui v0.5.0 h1:ri9VZLWHKIH/dq/AfkGe5F8976KWRmKb6ZqcCnyQB/4=
github.com/awesome-gocui/gocui v0.5.0/go.mod h1:1QikxFaPhe2frKeKvEwZEIGia3haiOxOUXKinrv17mA=
github.com/awesome-gocui/termbox-go v0.0.0-20190427202837-c0aef3d18bcc h1:wGNpKcHU8Aadr9yOzsT3GEsFLS7HQu8HxQIomnekqf0=
github.com/awesome-gocui/termbox-go v0.0.0-20190427202837-c0aef3d18bcc/go.mod h1:tOy3o5Nf1bA17mnK4W41gD7PS3u4Cv0P0pqFcoWMy8s=
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
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=

With 1.12, this runs, says "hello world", and exits with ctl-c.

With 1.13rc1, I get:

fatal error: freedefer with d._panic != nil

goroutine 1 [running]:
runtime.throw(0x1124ddf, 0x1e)
	/Users/josh/go/1.13/src/runtime/panic.go:774 +0x72 fp=0xc0000b1ca0 sp=0xc0000b1c70 pc=0x102a192
runtime.freedeferpanic()
	/Users/josh/go/1.13/src/runtime/panic.go:480 +0x36 fp=0xc0000b1cc0 sp=0xc0000b1ca0 pc=0x10296b6
runtime.freedefer(0xc0000b1dc8)
	/Users/josh/go/1.13/src/runtime/panic.go:423 +0x205 fp=0xc0000b1d40 sp=0xc0000b1cc0 pc=0x1029665
runtime.deferreturn(0xc00000e020)
	/Users/josh/go/1.13/src/runtime/panic.go:530 +0x6f fp=0xc0000b1d88 sp=0xc0000b1d40 pc=0x102976f
runtime: unexpected return pc for github.com/awesome-gocui/gocui.(*Gui).getTermWindowSize called from 0x11217e2
stack: frame={sp:0xc0000b1d88, fp:0xc0000b1e68} stack=[0xc0000b0000,0xc0000b2000)
000000c0000b1c88:  000000000000001e  000000c0000b1cb0 
000000c0000b1c98:  00000000010296b6 <runtime.freedeferpanic+54>  0000000001124ddf 
000000c0000b1ca8:  000000000000001e  000000c0000b1d30 
000000c0000b1cb8:  0000000001029665 <runtime.freedefer+517>  000000c0000b1ce0 
000000c0000b1cc8:  0000000001128af0  77ec80cc00000002 
000000c0000b1cd8:  000000c0000b1cf0  000000c0000b1d78 
000000c0000b1ce8:  00000000010c7f43 <os/signal.Notify+291>  00000000011ff660 
000000c0000b1cf8:  0000000001140700  000000c0000b1d40 
000000c0000b1d08:  0000000001032e8f <runtime.exitsyscallfast+207>  000000c000024000 
000000c0000b1d18:  000000c0000b1d50  000000000103259c <runtime.reentersyscall+124> 
000000c0000b1d28:  000000c000000180  000000c0000b1d78 
000000c0000b1d38:  000000000102976f <runtime.deferreturn+111>  000000c0000b1dc8 
000000c0000b1d48:  000000c0000b1df8  0000000003980364 
000000c0000b1d58:  000000c000000180  0000000001140700 
000000c0000b1d68:  000000c0000b1dc8  000000c0000b1e58 
000000c0000b1d78:  000000c0000b1e58  00000000010d8619 <github.com/awesome-gocui/gocui.(*Gui).getTermWindowSize+761> 
000000c0000b1d88: <000000c00000e020  0000000000000001 
000000c0000b1d98:  000000c00008e360  000000c00008e480 
000000c0000b1da8:  000000c00000e020  000000c0000b1dc4 
000000c0000b1db8:  00000000010ff5a0  000000000100bd01 <runtime.largeAlloc+353> 
000000c0000b1dc8:  00000000011432a0  00000000011406f8 
000000c0000b1dd8:  00000000011432a0  0000000000000000 
000000c0000b1de8:  000000c0000b1e98  00000000010d59e8 <github.com/awesome-gocui/gocui.NewGui+264> 
000000c0000b1df8:  000000c0000e4090  00000000000001b2 
000000c0000b1e08:  00000000000000b8  0000000000000000 
000000c0000b1e18:  0000000000000000  000000c0000e4090 
000000c0000b1e28:  000000c0000b1f50  00000000010db191 <main.main+65> 
000000c0000b1e38:  0000000000000001  00000000010ff400 
000000c0000b1e48:  000000c000094140  000000c0000b1ef0 
000000c0000b1e58:  00000000010dac73 <github.com/awesome-gocui/gocui.init+275> !00000000011217e2 
000000c0000b1e68: >000000000000000c  0000000001142ea0 
000000c0000b1e78:  000000c000094140  000000c0000b1f20 
000000c0000b1e88:  0000000001037bca <runtime.doInit+138>  00000000011e6380 
000000c0000b1e98:  000000c000044750  000000c0000b1f50 
000000c0000b1ea8:  000000000100535f <runtime.closechan+479>  000000c000072058 
000000c0000b1eb8:  0000000000000000  0000000000000000 
000000c0000b1ec8:  0000000000000000  00000000010f0320 
000000c0000b1ed8:  000000c000072058  000000c0000b1fd0 
000000c0000b1ee8:  000000000102bb1e <runtime.main+542>  000000c000072000 
000000c0000b1ef8:  0000000000000000  000000c000072000 
000000c0000b1f08:  0000000000000000  0000000000000000 
000000c0000b1f18:  0000000000000000  0000000000000008 
000000c0000b1f28:  000000c0000b1f60  000000000102ba04 <runtime.main+260> 
000000c0000b1f38:  0000000001128880  0000000000000000 
000000c0000b1f48:  0000000000000000  000000c0000b1f87 
000000c0000b1f58:  000000c000000180  0000000000000000 
github.com/awesome-gocui/gocui.(*Gui).getTermWindowSize(0xc, 0x1142ea0, 0xc000094140, 0xc0000b1f20, 0x1037bca)
	/Users/josh/pkg/mod/github.com/awesome-gocui/gocui@v0.5.0/gui.go:791 +0x2f9 fp=0xc0000b1e68 sp=0xc0000b1d88 pc=0x10d8619

goroutine 18 [syscall]:
os/signal.signal_recv(0x11432a0)
	/Users/josh/go/1.13/src/runtime/sigqueue.go:144 +0x96
os/signal.loop()
	/Users/josh/go/1.13/src/os/signal/signal_unix.go:23 +0x22
created by os/signal.init.0
	/Users/josh/go/1.13/src/os/signal/signal_unix.go:29 +0x41

goroutine 20 [select]:
github.com/awesome-gocui/termbox-go.Init.func1()
	/Users/josh/pkg/mod/github.com/awesome-gocui/termbox-go@v0.0.0-20190427202837-c0aef3d18bcc/api.go:95 +0x32f
created by github.com/awesome-gocui/termbox-go.Init
	/Users/josh/pkg/mod/github.com/awesome-gocui/termbox-go@v0.0.0-20190427202837-c0aef3d18bcc/api.go:92 +0x6c5
exit status 2

Note that this will shred your terminal window, so don't reproduce this in a window in which you have history you care about.

Tentatively marking as release blocker. I don't plan to investigate further at the moment, unless others cannot reproduce.

cc @randall77 @aclements @ianlancetaylor

@randall77
Copy link
Contributor

I can't reproduce that error. Instead I get a different one:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x10 pc=0x494547]

goroutine 1 [running]:
os.(*File).Close(0x10, 0x6, 0x5413)
	/usr/local/google/home/khr/Downloads/go1.13rc1/src/os/file_unix.go:233 +0x27
github.com/awesome-gocui/gocui.(*Gui).getTermWindowSize(0xc0000fa000, 0x78, 0x30, 0x0, 0x0)
	/usr/local/google/home/khr/gopath/pkg/mod/github.com/awesome-gocui/gocui@v0.5.0/gui.go:791 +0x2f4
github.com/awesome-gocui/gocui.NewGui(0x1, 0x4fd000, 0xc000010310, 0xc000059ef0, 0x4d8153)
	/usr/local/google/home/khr/gopath/pkg/mod/github.com/awesome-gocui/gocui@v0.5.0/gui.go:107 +0x108
main.main()
	/usr/local/google/home/khr/gowork/issue33841/main.go:11 +0x41

@josharian
Copy link
Contributor Author

Does it function correctly for you with 1.12.x?

@randall77
Copy link
Contributor

Yes.

@josharian
Copy link
Contributor Author

Excellent; glad you can at least reproduce something. :) Let me know if/how I can be of help.

@ianlancetaylor ianlancetaylor added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Aug 26, 2019
@randall77
Copy link
Contributor

I have a theory. The code does this:

	var sz struct {
		rows uint16
                cols uint16
        }
        ...
        defer out.Close()
        ...
            	_, _, _ = syscall.Syscall(syscall.SYS_IOCTL,
			out.Fd(), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&sz)))

The sz variable gets allocated on the stack just before the on-stack defer record.
The defer gets queued first, and then the syscall happens. This syscall actually writes more data than just the 4 bytes of the sz variable, overwriting the defer record.

The ioctl manpage says this is the structure:

 struct winsize {
               unsigned short ws_row;
               unsigned short ws_col;
               unsigned short ws_xpixel;   /* unused */
               unsigned short ws_ypixel;   /* unused */
           };

I think it's writing something to those two additional fields.

Adding 4 bytes of padding to the end of that structure fixes the bug.

@ianlancetaylor
Copy link
Contributor

CC @mattn

@randall77
Copy link
Contributor

I'm going to close this as not a bug in Go.
I've commented on the gocui bug: awesome-gocui/gocui#33

@josharian
Copy link
Contributor Author

Thanks, Keith, and sorry for the fire drill.

@golang golang locked and limited conversation to collaborators Aug 25, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. release-blocker
Projects
None yet
Development

No branches or pull requests

4 participants