-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
text/template: provide full stacktrace when the function call panics #59400
Comments
cc @robpike |
I don't see any reason for this to be a proposal, so taking it out of the proposal process. Can you show us a complete, standalone example that demonstrates the problem? I don't understand it from the description. Thanks. |
The background is: we have a very complex function to be called in template: func (t *Type) TheComplexFunc() {
func1()...
func2()...
while ... {
if (func3()) {
TheBuggyFunc()
} else {
func4()
}
}
func5()
} Then we call the
Since the But in error log, we only see:
We can find the problem in first time. Related issue: go-gitea/gitea#23872 |
It's impossible to be sure without an example, but I think you are referring to https://go.googlesource.com/go/+/refs/heads/master/src/text/template/funcs.go#355 . When a template calls a function, and the function panics, the template turns that into an error. That means that the default stack trace will not appear. I don't think that we can change that behavior today. That would be too likely to break existing working code. |
To avoid breaking, how about allowing developers to use a self-defined panic handler? func safeCall(fun reflect.Value, args []reflect.Value) (val reflect.Value, err error) {
defer func() {
if r := recover(); r != nil {
rErr := t.panicHandler(r) // <------ HERE
if e, ok := rErr.(error); ok {
err = e
} else {
err = fmt.Errorf("%v", rErr)
}
}
}()
...
}
t.SetPanicHandler(func (v any) error {
// we have a chance to handle the panic
})
t.Execute(...) |
Hi @ianlancetaylor , what do you think about this proposal? |
I would rather not make this change for a number of reasons, compatibility being one. But to find your bug you can either fork the package to add the traceback code (easy), delete the defer block (even easier), or just use a debugger (maybe easy, depending on the environment), which will in effect breakpoint when the trap happens before the template package catches it. In other words, it is your responsibility to find the bug, not the library's. And really, it should be very easy to do. |
Sorry but I didn't see any compatibility problem here, we just need to add a new function, nothing breaks. If there is any compatibility problem, please let me know.
If a developer could catch the panic stacktrace in first time, why they should do so much unnecessary work? Especially for a production rare crash. A clear stacktrace saves everyone's time. It's really helpful.
It is developer's responsibility to find bugs, but it's framework / language's responsibility to help developers to find bug, instead of hiding important clues / just returning an unclear error message. I would say the
In many cases, not that easy. If framework could help, it is easier. Could you please re-consider about this proposal? Thank you very much. |
This issue is related to the fact that I don't think For example, one could consider setting the environment variable |
Rather than change the libraries by requiring them to examine an environment variable, which will lead to a cascade of clunky changes, we could instead - as @ianlancetaylor may be saying above - just change the runtime to disable recovery of traps and panics (separately; panic is often used programmatically and it may just break things to disable it completely, while a trap caused by an array index out of bounds or a floating-point error is almost universally a bug). |
This problem is different from
I do not think For example, many large projects like Gitea, it uses quite a lot of 3rd packages, and it self sometimes also uses In a busy production system, before the race panic occurs, a lot of other unrelated panics would occur ahead, I can't imagine the |
As @robpike says we can just disable recovering a runtime panic, while still recovering an explicit call to To be clear, I'm not sure whether this is a good idea. |
I see, if runtime panics like |
@ianlancetaylor If it breaks something, it's would only be under the flag, where almost by definition it is OK, compatibility-wise. If we do anything, this seems the best. Programming each library to handle panics differently sometimes would be a mess. |
Hello, is there some progress? We meet new runtime panic - error again go-gitea/gitea#24342 (comment) , it's really difficult to debug, developers have to write a lot of temp "recover" code. |
Just to add a data point, I have
and it's there solely for use with template functions, and every time it's a nuisance and takes a bunch of guesswork to debug, and every time I wish template didn't ever recover from panics. I'd welcome an option to disable recover in safeCall for text/template specifically. I never want those panics to be recovered from, not even in production, so would just disable recovery permanently. Like others noted, other panic recoveries (in net/http, for example) are not a problem, this really is specific to templates. |
Ping, could the proposal be considered and accepted? |
I don't think we know exactly what to do. Do you want to try writing a trial implementation? |
Some approaches:
(I can see that there were already some options like "missingkey=zero", so adding a new option for the panic behavior seems not that difficult or breaking) Which one do you prefer? Or could there be more possible approaches? |
I still prefer doing nothing. If you want a traceback, edit safeCall to not recover. The existing behavior is right almost always. |
Sorry but I didn't get the point. How could "the existing behavior (hide the panic stacktrace)" be "right"? It causes some template function calls hard to debug their panics. There are also other reports like #59400 (comment) .
Do you mean every developer who uses Golang template should learn to build Go compiler/packages from source and use their home-made toolchain to debug the panics? I do not think it is friendly to developers and the eco-system. |
@ianlancetaylor what do you think about these possible approaches? IMO the option 4 (reuse the option function: |
I think that some version of option 3 seems workable. If |
I feel it's a bad precedent to start including true stack traces in errors. If you need to do something - and it still seems to me that you don't - an opt-in option that disables error recover feels right. |
At the moment, the code is:
If the function in template panics:
{{.TheUnstableFunc}}
, users and developers only know that it panics, but there is no stracktrace.In a complex system, the template functions could also be complex, without stacktrace, it's difficult to locate the root problem.
It's really helpful to provide a full stacktrace when the template function panics.
We have encounters a related bug today, the
TheUnstableFunc
has concurrency bug, template package only reportsruntime error: slice bounds out of range [2:1]
, it costs a lot of time for debugging the bug.Thank you.
The text was updated successfully, but these errors were encountered: