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

Show stacktrace buffers for sync requests #1420

Closed
bbatsov opened this issue Nov 14, 2015 · 17 comments
Closed

Show stacktrace buffers for sync requests #1420

bbatsov opened this issue Nov 14, 2015 · 17 comments
Milestone

Comments

@bbatsov
Copy link
Member

bbatsov commented Nov 14, 2015

Right now when something goes wrong in nrepl-send-sync-request we just dump the stacktrace in the REPL buffer and switch to it. Obviously, this is less than ideal. The reason why we're not showing our custom pretty stacktraces is that for cider middleware requests (which are generally done synchronously) *e doesn't get bound to the last exception and our stacktrace printing middleware doesn't work.

@bbatsov
Copy link
Member Author

bbatsov commented Nov 14, 2015

Just to add a bit more details here. I think the root cause of the issue is that we decided not to associate cider's custom middleware requests with a session. As I said I'm contemplating what's the best course of action and I definitely wouldn't mind some suggestions. @cemerick What would you recommend us to do?

@Malabarba
Copy link
Member

Could we write a middleware that wraps around all others and sets *e when appropriate?

@bbatsov
Copy link
Member Author

bbatsov commented Nov 14, 2015

Could we write a middleware that wraps around all others and sets *e when appropriate?

This idea also came to my mind, but this would also require changes to the way we request the stacktrace from the Elisp code. And I was also wondering if we might need more such data in the future. So maybe it makes sense to leverage the tooling session with the middleware... Anyways, if I had really great ideas - I would have implemented something by now. I'm definitely open to any suggestion/idea whatever.

P.S. If we do some wrapper middleware it'd be nice if it did exception handling in general, so we'd avoid deadlocks on unhandled exceptions. Something like this would eliminate the need for the current notion of "sync timeout".

@bbatsov
Copy link
Member Author

bbatsov commented Nov 26, 2015

@Malabarba Another relatively simple idea would be require the session middleware in all the middleware we have and to set some different var (e.g. *e-middleware*) there, so we won't clobber the evaluation exceptions. Then the stacktrace requests will be checking for both.

@Malabarba Malabarba modified the milestones: v0.10, v0.11 Dec 11, 2015
@bbatsov
Copy link
Member Author

bbatsov commented Dec 27, 2015

@jeffvalk You might take a look at this, if you'd like.

@cichli
Copy link
Member

cichli commented Dec 27, 2015

I think the ideal solution to this would be one that doesn't rely on checking *e at all - since it could be altered from underneath us by other evaluations, and we obviously don't want to be altering it ourselves.

If we had a way of getting nREPL to convey exception values to our middleware, it could then work generically for either exceptions thrown by an eval or exceptions thrown by other middlewares. I'll open a JIRA with a proposed solution and link to it here :-).

@jeffvalk
Copy link
Contributor

Haven't looked at this closely, but at one point I did bake up a middleware that wraps eval and returns errors and compiler warnings as data. If that might be useful, I'll resurrect it.

@jeffvalk
Copy link
Contributor

Also, does anyone have a code example to illustrate the problem? If I just send nrepl-send-sync-request something that produces an error, like:

(nrepl-send-sync-request (list "op" "eval" "code" "(+ nil 1)")
                         (cider-current-connection))

the middleware seems to work fine.

@bbatsov
Copy link
Member Author

bbatsov commented Dec 27, 2015

The problem is an error that occurs in a non-eval operation - e.g. macroexpansion.

@bbatsov
Copy link
Member Author

bbatsov commented Dec 27, 2015

Try the macroexpand command on this (| indicates your cursor position):

(defmacro naughty-macro []
  (throw (ex-info "BANG!" {})))

(naughty-macro)|

@cichli
Copy link
Member

cichli commented Dec 27, 2015

Try something like:

(cider-macroexpand-expr "foo" nil)

edit: @bbatsov is too fast for me :-).

@jeffvalk
Copy link
Contributor

Got it. Thanks.

@jeffvalk
Copy link
Contributor

Is macroexpansion a special case? Or are there other middleware components that cause this?

Macroexpansion obviously has to handle arbitrary (possibly invalid) user code like eval. But other than these two, middleware should deal with reasonably defined inputs, I think. If so, adding session support for grabbing *e from macroexpansion seems the reasonable thing here.

Thoughts?

@bbatsov
Copy link
Member Author

bbatsov commented Dec 27, 2015

All non-eval middleware (e.g. completion, var-info, etc) we have suffer from this, so this should be added to all of them. Seems that the current state of things is just an oversight of ours - we didn't use the session in most middleware and this is the biggest problem...

@jeffvalk
Copy link
Contributor

I see your point. But practically speaking, how would var-info or completion require presenting a stacktrace to a user? An unhandled error there is a bug in CIDER, isn't it?

@bbatsov
Copy link
Member Author

bbatsov commented Dec 27, 2015

Well, it might a bug and it might be some situation that we can't do anything sensible about. At any rate - it'd be better to handle such exceptions the same way we handle eval exceptions. We can really suppress them, as this would make fixing the real issues too hard, and we can't really expect that everything will always work perfectly.

sanjayl added a commit to sanjayl/cider that referenced this issue Mar 19, 2016
Sync-call errors do not bind *e unlike eval-call errors. This made it
impossible to use the stacktrace middleware to create the nicely
analyzed and formatted stacktrace buffer (see Issue clojure-emacs#1420
clojure-emacs#1420).

In order to rectify this, the nREPL code was modified slightly to store
sync-call related errors and provide a mechanism for the stacktrace
middleware to retrieve and process these stored exceptions. This results
in the ability for sync-call related errors to be analyzed and presented
using the standard stacktract buffer.
sanjayl added a commit to sanjayl/cider that referenced this issue Mar 19, 2016
Sync-call errors do not bind *e unlike eval-call errors. This made it
impossible to use the stacktrace middleware to create the nicely
analyzed and formatted stacktrace buffer (see Issue clojure-emacs#1420
clojure-emacs#1420).

In order to rectify this, the nREPL code was modified slightly to store
sync-call related errors and provide a mechanism for the stacktrace
middleware to retrieve and process these stored exceptions. This results
in the ability for sync-call related errors to be analyzed and presented
using the standard stacktract buffer.
sanjayl added a commit to sanjayl/cider-nrepl that referenced this issue Mar 19, 2016
The u/err-info function will now automatically store exceptions in
simple map based single-use data store. This will allow the stacktrace
middleware to act on Exceptions that were not bound to *e. See bug 1420
in CIDER: clojure-emacs/cider#1420.

See also CIDER PR 1617: clojure-emacs/cider#1617
sanjayl added a commit to sanjayl/cider-nrepl that referenced this issue Mar 21, 2016
The u/err-info function will now automatically store exceptions in
simple map-based, single-use, FIFO-expiring data store. This will allow
the stacktrace middleware to act on Exceptions that were not bound
to *e. See bug 1420 in CIDER:
clojure-emacs/cider#1420.

See also CIDER PR 1617: clojure-emacs/cider#1617
sanjayl added a commit to sanjayl/cider-nrepl that referenced this issue Mar 21, 2016
The u/err-info function will now automatically store exceptions in
simple map-based, single-use, FIFO-expiring data store. This will allow
the stacktrace middleware to act on Exceptions that were not bound
to *e. See bug 1420 in CIDER:
clojure-emacs/cider#1420.

See also CIDER PR 1617: clojure-emacs/cider#1617
sanjayl added a commit to sanjayl/cider-nrepl that referenced this issue Mar 21, 2016
The u/err-info function will now automatically store exceptions in
simple map-based, single-use, FIFO-expiring data store. This will allow
the stacktrace middleware to act on Exceptions that were not bound
to *e. See bug 1420 in CIDER:
clojure-emacs/cider#1420.

See also CIDER PR 1617: clojure-emacs/cider#1617
sanjayl added a commit to sanjayl/cider-nrepl that referenced this issue Mar 31, 2016
The u/err-info function will now automatically store exceptions in
simple map-based, single-use, FIFO-expiring data store. This will allow
the stacktrace middleware to act on Exceptions that were not bound
to *e. See bug 1420 in CIDER:
clojure-emacs/cider#1420.

See also CIDER PR 1617: clojure-emacs/cider#1617
@bbatsov
Copy link
Member Author

bbatsov commented Apr 1, 2016

Fixed by #1645

@bbatsov bbatsov closed this as completed Apr 1, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants