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

Use runtime.CallersFrames to create StackFrames #113

Closed
wants to merge 8 commits into from

Conversation

aduong
Copy link

@aduong aduong commented Mar 26, 2019

Goal

Stack traces from errors.Error are incomplete and miss functions. In particular, inlined functions are missing.

Additionally, the tests for errors were failing.

Also fixes #44

Design

The change is to user runtime.CallersFrames to translate program counters to symbolic information as recommended by the golang docs.

Changeset

Added

errors.NewStackFrameFromRuntime

Removed

None

Changed

errors.Error.StackFrame

Tests

Unit tests were fixed to fail for the right reasons (stack frame content, not formatting). All unit tests were run and passed.

Outstanding Questions

errors.StackFrame.Func() still relies on runtime.FuncForPC which is less than ideal. Within the library, it is primarily used on constructor of StackFrames. One way to give the right Func would be to save the Func on the StackFrame itself on construction from a runtime.Frame.

Review

For the submitter, initial self-review:

  • Commented on code changes inline explain the reasoning behind the approach
  • Reviewed the test cases added for completeness and possible points for discussion
  • A changelog entry was added for the goal of this pull request
  • Check the scope of the changeset - is everything in the diff required for the pull request?
  • This pull request is ready for:
    • Initial review of the intended approach, not yet feature complete
    • Structural review of the classes, functions, and properties modified
    • Final review

For the pull request reviewer(s), this changeset has been reviewed for:

  • Consistency across platforms for structures or concepts added or modified
  • Consistency between the changeset and the goal stated above
  • Internal consistency with the rest of the library - is there any overlap between existing interfaces and any which have been added?
  • Usage friction - is the proposed change in usage cumbersome or complicated?
  • Performance and complexity - are there any cases of unexpected O(n^3) when iterating, recursing, flat mapping, etc?
  • Concurrency concerns - if components are accessed asynchronously, what issues will arise
  • Thoroughness of added tests and any missing edge cases
  • Idiomatic use of the language

The output of Stack() isn't stable across versions of Go and shouldn't be relied on.
That makes the tests fail against Go 1.10, 1.11, and 1.12 (possibly earlier too).

Instead, the stack frames in Error should be verified against the stack frames supplied by the runtime.
Although the stack frames may vary from runtime impl to impl and version to version, we are
comparing like for like so the tests shouldn't break.
The stack frame information in Error were got by various functions in the runtime pkg.
This is explicitly discouraged in the [docs](https://golang.org/pkg/runtime/#Callers) which
instead suggest to use runtime.CallersFrames to translate PCs to symbolic info.
This should be sufficient and robust against differing number of frames between runtimes
Not introduced until Go 1.9
@bengourley
Copy link
Contributor

Hi @aduong, thanks for the PR. Due to the scope of this it'll take us a while to get it reviewed. I can't give you an ETA at this point, but we have a lot of other higher priority things going on at the moment. Thanks for your patience!


// NewStackFrameFromRuntime populates a stack frame object from a runtime.Frame object.
func NewStackFrameFromRuntime(frame runtime.Frame) StackFrame {
pkg, name := packageAndName(frame.Func)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that frame.Func can still be nil sometimes. Might be worth attempting to salvage something from frame.Function in that case.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that seems reasonable. I've pushed a commit that does this.

@aduong
Copy link
Author

aduong commented Apr 2, 2019

Hi @aduong, thanks for the PR. Due to the scope of this it'll take us a while to get it reviewed. I can't give you an ETA at this point, but we have a lot of other higher priority things going on at the moment. Thanks for your patience!

@bengourley, thanks for the prompt response. If it helps, I can split this change set so that the failing tests are separate set. As it turns out, the error_test suite was already being skipped because it was platform-dependent. Part of this change set makes those tests platform independent.

@aduong aduong changed the base branch from master to next April 23, 2019 05:32
@aduong
Copy link
Author

aduong commented Nov 10, 2019

Sadly, it doesn't seem the team had the capacity to review this and this is probably too outdated. My team has been able to work around the issue. Perhaps this has been fixed in later versions.

@aduong aduong closed this Nov 10, 2019
@mathewbyrne
Copy link

Is there any chance of reviving this PR?

We're running into an issue where we have an incorrect stack trace being generated for a panic that looks to be corrected by this change. It's very difficult to debug further into the runtime, but seems like common sense to follow the guidance of the Go documentation:

To translate these PCs into symbolic information such as function names and line numbers, use CallersFrames. CallersFrames accounts for inlined functions and adjusts the return program counters into call program counters.

We may consider forking our own client to get this fix in, but if it this could be merged here that would be much preferable.

@xljones
Copy link
Contributor

xljones commented Sep 11, 2020

Hey @mathewbyrne, seen your message on #114 so we'll continue the conversation there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants