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

Exception on stdout causing jsonrpc parse error #85

Closed
elmisback opened this issue Nov 3, 2022 · 2 comments
Closed

Exception on stdout causing jsonrpc parse error #85

elmisback opened this issue Nov 3, 2022 · 2 comments

Comments

@elmisback
Copy link

tldr: Is there a way to have the language server not put errors into stdout/avoid exception printing when invoking the language server?

Hi, I'm a Magic Racket user (without much racket background, so there might be an easy fix) who is trying to figure out where a bug is coming from. I posted an issue in Magic Racket (Eugleo/magic-racket#77 (comment)). It seems like stdout+stderr are getting mixed by the language server, and Magic Racket is unable to handle the error because of an uncatchable underlying exception in the jsonrpc parsing library (microsoft/vscode-languageserver-node#870).

I have a program that looks like this:

#lang racket

(require plot/no-gui)
(local-require (only-in plot/no-gui [plot-file plot-file*]))

This leads to a message from the language server with a mixture of racket error and jsonrpc data, which I caught in the VSCode extension debugger:

Caught exn:
standard-module-name-resolver: contract violation
  expected: module-path?
  given: '(just-space #f (rename plot/no-gui b plot-file))
  context...:
   /home/elm/.local/share/racket/8.6/pkgs/racket-langserver/autocomplete.rkt:106:0: walk-module
   /home/elm/.local/share/racket/8.6/pkgs/racket-langserver/check-syntax.rkt:111:10
   /usr/share/racket/collects/racket/logging.rkt:43:0: with-intercepted-logging
   /home/elm/.local/share/racket/8.6/pkgs/racket-langserver/check-syntax.rkt:77:0: check-syntax
   /usr/share/racket/collects/racket/contract/private/arrow-val-first.rkt:486:18
   /home/elm/.local/share/racket/8.6/pkgs/racket-langserver/text-document.rkt:65:0: did-open!
   /usr/share/racket/collects/racket/contract/private/arrow-val-first.rkt:486:18
   [repeats 1 more time]
   /home/elm/.local/share/racket/8.6/pkgs/racket-langserver/main.rkt:54:2: consume

Caught exn in request "textDocument/documentSymbol"
hash-ref: no value found for key
  key: 'file:///home/elm/temp/tst.rkt
  context...:
   /home/elm/.local/share/racket/8.6/pkgs/racket-langserver/text-document.rkt:405:0: document-symbol
   /usr/share/racket/collects/racket/contract/private/arrow-val-first.rkt:486:18
   /home/elm/.local/share/racket/8.6/pkgs/racket-langserver/methods.rkt:26:0: process-message
   /usr/share/racket/collects/racket/contract/private/arrow-val-first.rkt:486:18
   /home/elm/.local/share/racket/8.6/pkgs/racket-langserver/main.rkt:54:2: consume

Content-Length: 117

{"error":{"code":-32603,"message":"internal error in method \"textDocument/documentSymbol\""},"id":1,"jsonrpc":"2.0"}

jsonrpc fails to find the Content-Length header in this buffer due to the error text, and after the first such error, all subsequent requests result in the same problem since there's extra stuff in the buffer and it's never cleared. So it seems like this is a problem with stdout getting mixed with stderr.

I tried setting -W0 etc. in the langserver args to turn off stderr messages, but stuff still came through. I also tried redirection using a shell with 2>/dev/null and executing the langserver after loading an initial file that sets current-error-port to nowhere:

const executable = {  // VSCode language client config
      command: '/bin/bash',
      args: ['xvfb-run', '--auto-servernum', 'racket','-f', '/home/elm/nostderr.rkt', '--lib', 'racket-langserver', '2>/dev/null' ],
      // options: {
      //   shell: true
      // }
    };

with nostderr.rkt:

#lang racket
(require (only-in racket/port open-output-nowhere))
(current-error-port (open-output-nowhere))

Those didn't work either. My understanding of how the VSCode language server actually runs the process based on the executable configuration above and how to configure ports in racket are weak, so there's probably something here that I'm missing. I was able to solve the issue by commenting out the relevant eprintf lines in a racket-langserver fork.

So basically it seems like what's needed is an option to turn off the error printing to the extent that it's possible, since Magic Racket doesn't have a way to gracefully handle printed errors until the PR for the issue I linked goes through (no activity since December 2021).

@6cdh
Copy link
Contributor

6cdh commented Feb 9, 2023

It's not related to stdout/stderr. That's an exception that happened in the didOpen method and didn't put it into the opened document hash table. Any other later requests will produce a hash-ref error.

A simple fix is to change local-require to require. Or waiting for it fixed by someone who really understands what happened :).

@elmisback
Copy link
Author

Thank you for having a look at this issue! While you might be right about the didOpen issue, my problem was actually because xvfb-run dumps stderr into stdout (!), so JSON-RPC was trying to read the report-error output. https://bugs.launchpad.net/ubuntu/+source/xorg-server/+bug/1059947. I confirmed in a debugger that the mixed stream caused the JSON-RPC parser to miss the content-length header and then lose its place forever.

I fixed this by modifying xvfb-run as suggested here: https://superuser.com/questions/1719253/xvfb-run-redirects-stdout-and-stderr-to-stdout-only. You may want to suggest this for other users who resort to using xvfb-run for running headless as mentioned in (#45).

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

No branches or pull requests

2 participants