Skip to content

runtime: wrong line number in panic call stack #5856

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

Closed
gopherbot opened this issue Jul 10, 2013 · 7 comments
Closed

runtime: wrong line number in panic call stack #5856

gopherbot opened this issue Jul 10, 2013 · 7 comments

Comments

@gopherbot
Copy link
Contributor

by daviddengcn:

1. What is a short input program that triggers the error?
package main

func PanicInGoSrc() {
    panic("panic")
}

var a string = "abc"

func doPanic() error {
    if a == "" {
        return nil  // Line 11
    }
    
    defer PanicInGoSrc()
    
    return nil          // Line 16
}

func main() {
    doPanic()
}

2. What is the full compiler output?
panic: panic

goroutine 1 [running]:
main.PanicInGoSrc()
        F:/job/go/src/wrongpanicline.go:4 +0x43
main.doPanic(0x0, 0x0)
        F:/job/go/src/wrongpanicline.go:11 +0x44
main.main()
        F:/job/go/src/wrongpanicline.go:20 +0x1e

goroutine 2 [runnable]:
exit status 2

3. What version of the compiler are you using?  (Run it with the -V flag.)
go version go1.1.1 windows/386

The line number in main.doPanic is not 11, should be 16, this confuse me a lot before I
found this is a compiler bug.
@gopherbot
Copy link
Contributor Author

Comment 1 by daviddengcn:

1. slightly modify the program, the line number changes (still wrong)
package main
func PanicInGoSrc() {
    panic("panic")
}
var a string = "abc"
func doPanic() {
    if a == "" {
        return // Line 11
    }
    
    defer PanicInGoSrc()
    
    return     // Line 16
}
func main() {
    doPanic()
}
2. compiler output
panic: panic
goroutine 1 [running]:
main.PanicInGoSrc()
        F:/job/go/src/wrongpanicline.go:4 +0x43
main.doPanic()
        F:/job/go/src/wrongpanicline.go:10 +0x21
main.main()
        F:/job/go/src/wrongpanicline.go:20 +0x1b
goroutine 2 [runnable]:
exit status 2

@robpike
Copy link
Contributor

robpike commented Jul 11, 2013

Comment 2:

This will likely be fixed by the pending changes to the representation of the PC/line
table.

Labels changed: added priority-later, removed priority-triage.

Status changed to Accepted.

@rsc
Copy link
Contributor

rsc commented Jul 12, 2013

Comment 3:

Actually it is unclear. Defer needs to be handled a bit better in the stack traces in
general. 
There are some good ideas on issue #5832, but there might be a real bug here, so I'm
leaving this one separate.

@minux
Copy link
Member

minux commented Jul 12, 2013

Comment 4:

the problem here is that the function only has a single call to
runtime.deferreturn, so we can't differentiate different return
statements.
unless our pcln table could map a single pc to multiple line
(and then we also has the problem of determine which one
to use)
we should make cmd/gc emit one runtime.deferreturn for
every return statement.

@rsc
Copy link
Contributor

rsc commented Jul 12, 2013

Comment 5:

I don't think we have to show the specific return statement: the return is over.
We could show line 17 (the final }), for example. But we can also recognize the
deferreturn pattern and print a note about this being a deferred call.

@rsc
Copy link
Contributor

rsc commented Jul 12, 2013

Comment 6:

I looked into having separate deferreturns, but it's tricky. 
The CALL deferreturn is already tagged with the line number of the function's closing },
but that line number is not actually relevant to the stack trace. The deferred function
call was set up through abnormal means, and it is _returning to_ the CALL deferreturn
instruction, not called by it. The traceback does what it always does, which is to print
the line number of the instruction before the return PC (in normal operation, that's the
CALL). Here, because the call was simulated by the runtime package, the instruction
before the return PC is completely unrelated. The way the code was laid out, it happens
to be something on line 11.
The solution is to emit a real no-op instruction with the correct line number before the
CALL deferreturn, so that when the traceback looks at the line number of the instruction
before the return PC, it will get the right answer.
goroutine 1 [running]:
main.PanicInGoSrc()
    /Users/rsc/x.go:4 +0x43
main.doPanic()
    /Users/rsc/x.go:17 +0x23
main.main()
    /Users/rsc/x.go:20 +0x1b

Owner changed to @rsc.

Status changed to Started.

@rsc
Copy link
Contributor

rsc commented Jul 12, 2013

Comment 7:

This issue was closed by revision 7e97d39.

Status changed to Fixed.

@golang golang locked and limited conversation to collaborators Jun 24, 2016
@rsc rsc removed their assignment Jun 22, 2022
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants