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: error returned by os.OpenFile blocks panic handler #14432

Closed
mxk opened this issue Feb 20, 2016 · 8 comments
Closed

runtime: error returned by os.OpenFile blocks panic handler #14432

mxk opened this issue Feb 20, 2016 · 8 comments
Milestone

Comments

@mxk
Copy link

mxk commented Feb 20, 2016

go1.6 windows/amd64 on Windows 8

The following program tries to create a new file with os.O_EXCL and panics if the file already exists. When panic(err) is called, "panic:" is written to stderr and the program blocks. You have to terminate it with Ctrl-C. If you uncomment err.Error() then you get a normal backtrace and the program exits.

I'm guessing that there is a problem with retrieving the error information in the panic handler, but if done before panicking, then everything works as expected.

package main

import "os"

func main() {
    _, err := os.OpenFile("tmp", os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
    if err != nil {
        //err.Error()
        panic(err)
    }
}
@bradfitz bradfitz added this to the Unplanned milestone Feb 21, 2016
@bradfitz
Copy link
Contributor

/cc @alexbrainman

@minux
Copy link
Member

minux commented Feb 21, 2016 via email

@minux
Copy link
Member

minux commented Feb 21, 2016 via email

@minux
Copy link
Member

minux commented Feb 21, 2016 via email

@aclements
Copy link
Member

Interesting. I wonder if we shouldn't be calling in to user code to format the panic message after freezing the world. Presumably on any platform, if an Error method calls cgo or does something nontrivial with goroutines or something, it would deadlock the system in the same way.

We could format all of the panic messages first, then freeze the world, then print them.

@aclements
Copy link
Member

This also means we're calling in to user code while holding a runtime lock (paniclk). For example, the following results in a "panic: fatal error: schedule: holding locks", which should not be triggerable by user code:

package main

import "runtime"

type e struct{}

func (e) Error() string {
    runtime.Gosched()
    return "error"
}

func main() {
    panic(e{})
}

@aclements
Copy link
Member

This one deadlocks on Linux (I haven't looked in to why the Println is necessary):

package main

/*
char *geterror() {
    return "error";
}
*/
import "C"
import "fmt"

type e struct{}

func (e) Error() string {
    fmt.Println("Hi!")
    return C.GoString(C.geterror())
}

func main() {
    panic(e{})
}

And this one panics with another internal error, "fatal error: stopm holding locks":

package main

import "fmt"

type e struct{}

func (e) Error() string {
    fmt.Println("Hi!")
    fmt.Println("Bye!")
    return "x"
}

func main() {
    panic(e{})
}

These both work in 1.4.3, but not 1.5.

@aclements aclements modified the milestones: Go1.7, Unplanned Feb 21, 2016
@gopherbot
Copy link

CL https://golang.org/cl/19792 mentions this issue.

@minux minux self-assigned this Feb 21, 2016
@golang golang locked and limited conversation to collaborators Feb 28, 2017
@rsc rsc unassigned minux Jun 23, 2022
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

5 participants