-
Notifications
You must be signed in to change notification settings - Fork 18.6k
Description
Sometimes gopls panics. Hopefully this is becoming increasingly rare, but by definition panics are unexpected and disruptive to the user experience. vscode-go improves the UX with special handling to identify and capture panics, but for other editor plugins the disruption can be completly opaque: gopls just stops working. Particularly when running gopls as a daemon, stderr is often /dev/null, and finding the panicking stack involves re-running the daemon and trying to reproduce the panic.
We can do better, by ensuring that stderr is always captured and doing our best to make it discoverable. Here is one way to achieve this:
- If os.Stderr is /dev/null:
- create a tempfile with 0600 permissions (conservative permissions since the caller didn't ask us to do this)
- Redirect stderr to this temp file (using
syscall.Dup2for POSIX systems, etc.) - defer a cleanup func that redirects back to /dev/null and then deletes the tempfile
- In the daemon, if
os.Stderris a normal file, tell the gopls forwarder about it during handshake. - In the forwarder, track whether "shutdown" or "exit" have been called by the LSP client. Detect abnormal daemon disconnection when "shutdown" or "exit" haven't been called.
- On abnormal exit from the daemon, before closing the client connection, inject a message to the effect of "The gopls daemon exited abnormally. Please check the output at
path/to/stderrand consider filing an issue at golang.org/issues"
The net effect of this should be that when the gopls daemon panics the deferred cleanup will not run and the temporary stderr will be persisted. Then, the LSP client will get a ShowMessage notification explaining what went wrong, and suggesting next steps.
CC @myitcv @leitzler @bhcleek, who might have opinions on this UX as plugin maintainers.