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

fix: wg.Done() must be outside RecoverRepanic #247

Merged
merged 2 commits into from Jun 15, 2020

Conversation

rhcarvalho
Copy link
Contributor

This is a small change to the example for correctness.
The concurrency issue is subtle, but here is an attempt to explain it.

Keep in mind that:

  • deferred calls happen in reverse order.
  • to recover from panics in f, RecoverRepanic must defer a func call
    before calling f.

If defer wg.Done() is part of f, the argument passed to RecoverRepanic,
it means it will be called before any deferred functions setup by
RecoverRepanic itself. If all goroutines started in the loop would call
wg.Done() before an event is reported to Sentry, the main goroutine
blocked on wg.Wait() would unblock and reach the end of func main,
terminating the execution of the program, consequently dropping any
other pending work in other goroutines, reporting to Sentry included.


I had this change locally and forgot to include in #241, my bad.

This is a small change to the example for correctness.
The concurrency issue is subtle, but here is an attempt to explain it.

Keep in mind that:
- deferred calls happen in reverse order.
- to recover from panics in f, RecoverRepanic must defer a func call
before calling f.

If defer wg.Done() is part of f, the argument passed to RecoverRepanic,
it means it will be called before any deferred functions setup by
RecoverRepanic itself. If all goroutines started in the loop would call
wg.Done() before an event is reported to Sentry, the main goroutine
blocked on wg.Wait() would unblock and reach the end of func main,
terminating the execution of the program, consequently dropping any
other pending work in other goroutines, reporting to Sentry included.
@rhcarvalho
Copy link
Contributor Author

@lmb, I'm sorry I forgot to include this in my original example.

While this PR doesn't change the implementation of RecoverRepanic and thus may not affect your own code, I thought of pinging you to make sure you don't copy my original mistake if you're using sync.WaitGroup or other patterns that may need similar deliberate care to make correct.

Also note that, as with panic() itself, an unhandled panic in one goroutine brings down the whole program, such that repanicking means that likely only one concurrent panic gets successfully reported to Sentry.

Even though already documented in the body of the function, promoting a
note right at the documentation of RecoverRepanic will hopefully raise
awareness for anyone trying to use the example.
@kamilogorek
Copy link
Contributor

Makes sense. Nice explanation 👌

@rhcarvalho rhcarvalho merged commit 050fc94 into getsentry:master Jun 15, 2020
@rhcarvalho rhcarvalho deleted the repanic-example branch June 15, 2020 13:46
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.

None yet

2 participants