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

RFC: Make JsonRpc to NOT swallow exceptions #29

Merged
merged 1 commit into from Jul 31, 2022

Conversation

artempyanykh
Copy link
Contributor

This is once again a continuation of #25.

There were several issues with the previous version.
Catching exceptions in server's code and turning them into LocalRpcExceptions probably isn't the best because:

  1. Notifications don't require a response, hence no error will be shown
    to the user. Effectively, this means any exceptions including fatal
    can get swallowed.
  2. The context of the original exception is lost in conversion.

This is a breaking change and may not be desirable for servers that use exception for control flow/recovery. But I think the spirit of the library is such that

  • Recoverable (user reportable) errors are encoded as LspResult's Error.
  • Exceptions are non-recoverable and should terminate the server.

Note: since now we're awaiting jsonRpc.Completion which completes when connection is closed, I could clean up a workaround for VSCode's incorrect shutdown sequence.

This is once again a continuation of ionide#25.

There were several issues with the previous version.
Catching exceptions in server's code and turning them into LocalRpcExceptions probably isn't the best because:
1. Notifications don't require a response, hence no error will be shown
   to the user. Effectively, this means any exceptions including fatal
   can get swallowed.
2. The context of the original exception is lost in conversion.
artempyanykh added a commit to artempyanykh/marksman that referenced this pull request Jul 31, 2022
@artempyanykh
Copy link
Contributor Author

As an example, with this change I'm getting an error and a stack trace like this in lsp logs, when the server hits failwith or other kind of unrecoverable error:

Unhandled exception: System.AggregateException: One or more errors occurred. (Exception has been thrown by the target of an invocation.)
 ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> System.Exception: Planted error!
   at Marksman.Server.MarksmanServer.TextDocumentDidChange(DidChangeTextDocumentParams par) in /Users/arr/dev/marksman/Marksman/Server.fs:line 411
   at Ionide.LanguageServerProtocol.Server.Pipe #1 input at line 183@187-4.Invoke(server s, DidChangeTextDocumentParams p) in /Users/arr/dev/marksman/LanguageServerProtocol/LanguageServerProtocol.fs:line 187

@baronfel
Copy link
Contributor

Whereas before that same error would be transmitted to the client and just show the exception message?

@artempyanykh
Copy link
Contributor Author

artempyanykh commented Jul 31, 2022

@baronfel not quite. In this case the exception happened in textDocument/didChange and previously it would just get swallowed by JsonRpc because notifications don't require a response.

They actually mention this here:
image

@baronfel
Copy link
Contributor

Well overall I'd prefer to have the information, so let's take this change :)

@baronfel baronfel merged commit 114bd9c into ionide:main Jul 31, 2022
@artempyanykh
Copy link
Contributor Author

Coolio! 🤘 As I see it, the only questionable part in this PR is:

use jsonRpc =
       { new JsonRpc(jsonRpcHandler) with
           member this.IsFatalException(ex: Exception) = true }

In case dying on exceptions will prove to be no bueno, we could make this thing configurable.

@artempyanykh artempyanykh deleted the exceptions branch July 31, 2022 23:26
razzmatazz added a commit to razzmatazz/LanguageServerProtocol that referenced this pull request Aug 23, 2022
It appears that ionide#29 broke the reporting of
LspResult.Error to StreamJsonRpc.

StreamJsonRpc processes LocalRpcException to report exceptions/errors from request handlers.
In particular we have code in `requestHandling` that actually throws LocalRcpException when
handler returns LspResult.Error.

This commit adds code to skip markingLocalRcpException as a fatal exception and make it not
crash the server.
@razzmatazz
Copy link
Contributor

razzmatazz commented Aug 23, 2022

Coolio! 🤘 As I see it, the only questionable part in this PR is:

use jsonRpc =
       { new JsonRpc(jsonRpcHandler) with
           member this.IsFatalException(ex: Exception) = true }

In case dying on exceptions will prove to be no bueno, we could make this thing configurable.

uh.. there are actually some problems with this, regarding handling of LspResult.Error -- see #33

baronfel pushed a commit that referenced this pull request Aug 23, 2022
It appears that #29 broke the reporting of
LspResult.Error to StreamJsonRpc.

StreamJsonRpc processes LocalRpcException to report exceptions/errors from request handlers.
In particular we have code in `requestHandling` that actually throws LocalRcpException when
handler returns LspResult.Error.

This commit adds code to skip markingLocalRcpException as a fatal exception and make it not
crash the server.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants