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

OTP 21 compatibility when using stack traces #193

Merged
merged 6 commits into from
Jul 11, 2018

Conversation

massemanet
Copy link
Contributor

There is no good solution if you want BOTH
a) be able to compile with both pre- and post-21 compilers
b) no warning (e.g. if you use warnings_as_errors)
This is, hopefully, one of the less bad hacks.

There is no good solution if you want BOTH
a) be able to compile with both pre- and post-21 compilers
b) no warning (e.g. if you use warnings_as_errors)
This is, hopefully, one of the less bad hacks.
We introduce the macro 'try_with_stack/1' which runs it's argument inside a
try. It returns either {ok, Result} or {Class, Reason, Stacktrace}.
The macro has two different implementations; post-21 (try catch C:R:S) and
pre-21 (get_stacktrace/0).
We use the 'OTP_RELEASE' directive, which was introduced in 21, to decide
between post- and pre-21.
@paulo-ferraz-oliveira
Copy link
Contributor

Have you looked at https://github.com/g-andrade/stacktrace_compat

I was going to do a PR to add this, but it seems there's already two PRs related to get_stacktrace's deprecation.

@massemanet
Copy link
Contributor Author

Had not seen stacktrace_compat. looks nice.
I'm fine with closing my PR, changing it to use stacktrace_compat, or implementing a bespoke parse transform. I personally prefer to avoid parse transforms, but for this particular use case it might be the Right Thing.

@eproxus
Copy link
Owner

eproxus commented Jul 10, 2018

Sorry for not having looked at this sooner. I actually wanted to merge the solution from this PR and #192 because I like keeping the try-catch statements as-is. As for the stack trace library, I would like to avoid including it since I don't want to have any dependencies, especially for such a small thing, and I agree with @massemanet that parse transforms should be avoided if possible.

@massemanet Do you think you could refactor this to keep the try-catch statements intact? I prefer your code because of the clarity and documentation. 🙂

@massemanet
Copy link
Contributor Author

sure. I disliked #192 because the -> is hidden in the macro. that'll break all source code analysis tools.
my solution otoh hides the fact that there's a try...

@eproxus
Copy link
Owner

eproxus commented Jul 10, 2018

@massemanet Ah, missed that nuance.

I guess one alternative would be two macros?

-ifdef(OTP_RELEASE).
-define(STACKTRACE, St0).
-define(WITH_STACKTRACE(T, R), T:R:St0).
-else.
-define(STACKTRACE, erlang:get_stacktrace()).
-define(WITH_STACKTRACE(T, R, S), T:R).
-endif.

% then

try
    X
catch
    ?WITH_STACKTRACE(Class, Reason) ->
        St = ?STACKTRACE,
        % ...
end

@massemanet
Copy link
Contributor Author

massemanet commented Jul 10, 2018

I disliked the two macro solution too, because now you have two problems (or three?)... (Real problem might be that I'm just an internet hater...)
Anyway, your solution won't work because ?WITH_STACKTRACE has different arities depending on the define(OTP_RELEASE) (or does that magically work?). + leaking St0 is a bit debatable.
I did implement a variant with two macros that seems not too bad.

@massemanet
Copy link
Contributor Author

massemanet commented Jul 10, 2018

I see now that the S in WITH_STACKTRACE(T, R, S) is a typo(?) Never mind then.
Probably bad to leak St0 in any case.

@paulo-ferraz-oliveira
Copy link
Contributor

I'm OK with whatever solution, as long as it works seemlessly with OTP-19 and OTP-21, for example.

@eproxus
Copy link
Owner

eproxus commented Jul 11, 2018

@massemanet Looks good so far. A few more issues/questions before I merge:

  • Just curious, what's the ignored # files for? Emacs?
  • Would it make sense to move the inner try-catch into do_eval? I have the feeling do_eval doesn't do much right now
  • Can we get rid of the single letter variable names? It would make the code a bit more readable. It could be done by making Exception = {Class, Reason, Stacktrace} and passing that tuple into handle_exception/7 and raise/7 instead of the individual arguments

@massemanet
Copy link
Contributor Author

  • the ignored files are indeed emacs tmp files. Old habit...
  • tried un-nesting the tries, looks nice imo.
  • I made all the variable names more descriptive, and added a bit more doc.

I also ran dialyzer. There's some warnings, but none seems related to my changes (I did fix an unrelated buggy spec)

@eproxus
Copy link
Owner

eproxus commented Jul 11, 2018

Looks very good! Thanks!

@eproxus eproxus merged commit dc6a669 into eproxus:master Jul 11, 2018
@massemanet massemanet deleted the workaround-get_stacktrace branch July 11, 2018 10:36
@paulo-ferraz-oliveira
Copy link
Contributor

Any chance this gets a tag soon?

@eproxus
Copy link
Owner

eproxus commented Jul 12, 2018

@paulo-ferraz-oliveira Thanks for reminding me. I'll release a new version today!

@eproxus eproxus changed the title Workaround get_stacktrace removal OTP 21 compatibility when using stack traces Jul 12, 2018
@eproxus
Copy link
Owner

eproxus commented Jul 12, 2018

@paulo-ferraz-oliveira @massemanet Fix is in 0.8.11.

@paulo-ferraz-oliveira
Copy link
Contributor

@eproxus: thanks much; it's working as expected.

@eproxus
Copy link
Owner

eproxus commented Jul 12, 2018

Thanks @massemanet and @getong!

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

3 participants