Skip to content

Fix errors on empty stacktraces #3042

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

Merged
merged 4 commits into from
Sep 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

### Bugs fixed

* [#3022](https://github.com/clojure-emacs/cider/issues/3022): Handle empty stacktraces, pointing users to docs about the OmitStackTraceInFastThrow JVM optimization.
* [#3020](https://github.com/clojure-emacs/cider/issues/3020): Fix session linking on Windows, e.g. when jumping into a library on the classpath.
* [#3031](https://github.com/clojure-emacs/cider/pull/3031): Fix `cider-eval-defun-up-to-point` failing to match delimiters correctly in some cases, resulting in reader exceptions.
* [#3039](https://github.com/clojure-emacs/cider/pull/3039): Allow starting the sideloader for the tooling session
Expand Down
55 changes: 31 additions & 24 deletions cider-stacktrace.el
Original file line number Diff line number Diff line change
Expand Up @@ -677,30 +677,37 @@ others."
"Emit into BUFFER function call site info for the stack FRAME.
This associates text properties to enable filtering and source navigation."
(with-current-buffer buffer
(nrepl-dbind-response frame (file line flags class method name var ns fn)
(let ((flags (mapcar 'intern flags))) ; strings -> symbols
(insert-text-button (format "%26s:%5d %s/%s"
(if (member 'repl flags) "REPL" file) line
(if (member 'clj flags) ns class)
(if (member 'clj flags) fn method))
'var var 'class class 'method method
'name name 'file file 'line line
'flags flags 'follow-link t
'action 'cider-stacktrace-navigate
'help-echo (cider-stacktrace-tooltip
"View source at this location")
'font-lock-face 'cider-stacktrace-face
'type 'cider-plain-button)
(save-excursion
(let ((p4 (point))
(p1 (search-backward " "))
(p2 (search-forward "/"))
(p3 (search-forward-regexp "[^/$]+")))
(put-text-property p1 p4 'font-lock-face 'cider-stacktrace-ns-face)
(put-text-property p2 p3 'font-lock-face 'cider-stacktrace-fn-face)
(put-text-property (line-beginning-position) (line-end-position)
'cider-stacktrace-frame t)))
(insert "\n")))))
(if (null frame) ;; Probably caused by OmitStackTraceInFastThrow
(let ((url "https://docs.cider.mx/cider/troubleshooting.html#empty-java-stacktraces"))
(insert " No stacktrace available!\n Please see ")
(insert-text-button url
'url url
'follow-link t
'action (lambda (x) (browse-url (button-get x 'url)))))
(nrepl-dbind-response frame (file line flags class method name var ns fn)
(let ((flags (mapcar 'intern flags))) ; strings -> symbols
(insert-text-button (format "%26s:%5d %s/%s"
(if (member 'repl flags) "REPL" file) line
(if (member 'clj flags) ns class)
(if (member 'clj flags) fn method))
'var var 'class class 'method method
'name name 'file file 'line line
'flags flags 'follow-link t
'action 'cider-stacktrace-navigate
'help-echo (cider-stacktrace-tooltip
"View source at this location")
'font-lock-face 'cider-stacktrace-face
'type 'cider-plain-button)
(save-excursion
(let ((p4 (point))
(p1 (search-backward " "))
(p2 (search-forward "/"))
(p3 (search-forward-regexp "[^/$]+")))
(put-text-property p1 p4 'font-lock-face 'cider-stacktrace-ns-face)
(put-text-property p2 p3 'font-lock-face 'cider-stacktrace-fn-face)
(put-text-property (line-beginning-position) (line-end-position)
'cider-stacktrace-frame t)))
(insert "\n"))))))

(defun cider-stacktrace-render-compile-error (buffer cause)
"Emit into BUFFER the compile error CAUSE, and enable jumping to it."
Expand Down
28 changes: 19 additions & 9 deletions doc/modules/ROOT/pages/troubleshooting.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -269,16 +269,10 @@ counting from 0 while Clojure starts from 1. Accordingly, the `cider-nrepl`
middleware uses 1-based indexing and all conversions to 0-based indexing should
be handled client-side. See https://github.com/clojure-emacs/cider/issues/2852.

=== Empty Java stacktraces resulting in `NullPointerException`
Copy link
Contributor Author

Choose a reason for hiding this comment

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

(I removed this clause since it's not clear that the stacktraces are only omitted for NPEs or cause them to occur)

=== Empty Java stacktraces

Occasionally the JVM might remove some stack frames, which will break
CIDER's stacktrace display functionality, resulting in error message like these:

[source]
----
error in process filter: cider-stacktrace-render-frame: Format specifier doesn’t match argument type
error in process filter: Format specifier doesn’t match argument type
----
Occasionally the JVM might remove some stack frames, resulting in no stacktrace
information being displayed in CIDER's error buffer.

That's caused by an JVM optimization (`OmitStackTraceInFastThrow`, enabled by
default), which optimizes "built-in" exceptions that are thrown frequently enough
Expand All @@ -287,4 +281,20 @@ to be cached and have no stacktrace.
You can turn off the optimization by adding the JVM flag `-XX:-OmitStackTraceInFastThrow` to whatever
command you're using to start nREPL.

In particular, by adding it to a deps.edn file under an alias (eg. `:dev`)
[source,lisp]
---
{:aliases
{:dev
{:jvm-opts ["-XX:-OmitStackTraceInFastThrow"]
...}}}
---

Or by customising the jack-in options.
[source,lisp]
---
(setq cider-clojure-cli-global-options "-J-XX:-OmitStackTraceInFastThrow")
---


TIP: You can read more about this problem https://github.com/clojure-emacs/cider/issues/3022[here].