Open shir opened 5 years ago
And based on that I see in the Output window parameter ruby.lintDebounceTime
doesn't work and linter is called on every char I type.
lintDebounceTime
is deprecated and not used in the language server. There are multiple reasons for this but mostly the way the linter is architected in the server allows for lint calls to be aborted when a new one comes in.
Some of this is the nature of running the linter: Rubocop is already a touch slow and adding in the cost of shelling out + the startup time of the bundler environment makes it slower still.
Out of curiosity, on these large files, how long does it take the Rubocop command to execute on the command line?
for one large file with which I have the issue (several runs and values are around this):
real 0m1.211s
user 0m0.899s
sys 0m0.268s
Another large file with which I have the issue:
real 0m1.226s
user 0m0.934s
sys 0m0.279s
Here are values for a small file for which I don't have any issues:
real 0m1.196s
user 0m0.912s
sys 0m0.277s
Looks like pretty similar. But the output is very different: for large files, I have 524 and 130 rubocop problems.
Can you also check running Rubocop via stdin
?
cat foo.rb | rubocop -s foo.rb ....
It looks like the actual issue here is that the Rubocop spawn is getting terminated early as expected but for some reason an EPIPE
is slipping past the error handing and causing the server to go down. I'm guessing were that not to happen the last lint would succeed and come back.
@wingrunr21
Here is time for a large file with the issue using stdin:
real 0m1.878s
user 0m1.638s
sys 0m0.221s
Here is time for another large file with the issue:
real 0m1.311s
user 0m1.094s
sys 0m0.211s
Here is time for a small file with no issue:
real 0m1.135s
user 0m0.923s
sys 0m0.209s
k thanks. That extra 500ms really shouldn't be affecting things. I think it's likely what I said before: the EPIPE is not being handled which brings down the server.
If you are able to provide me an example file that'd really help in chasing down how to handle this use case. Otherwise I can just generate a file with a ton of errors.
@wingrunr21
I've just made a test: created a file with line Rails.logger.debug 'something'
repeated >500 times. The file has 590 lines and no rubocop errors. I've started typing at the end of the file and got the same issue. So it looks like it depends on file size but not on a number of rubocop errors
Great, I can use that as a starting point. Thanks
@wingrunr21 Any luck with this? I can also reliably reproduce this if I can be of help. I'm also happy to take a stab at a fix if you can give me any pointer on where to look. Thanks for all your work on this project ❤️
@MikeMcQuaid I'm not the author but I've tried to figure out this issue. Unfourtanelty I don't know Rx so didn't make a lot. My thoughts: When you type fast, the previous instance of a rubocop is killed and spawn
from spawn-rx
tries to clean observers, but if the previous observer doesn't finish his job he may try to access data which do not exist anymore. Because of my (not) knowledge, I couldn't confirm it.
Yes that’s what is happening. The observer will automatically cancel on the next lint request. But node tries to read from a broken pipe and fires an uncatchable exception (this and similar issues have been pretty hard to mitigate).
I want to provide an option to only lint on save. The other option would be to denounce the lints but I really don’t want to do that.
@wingrunr21 may just add an error handling somewhere above to cover all similar errors?
Can’t handle an uncatchable exception 😛
There is already error handling in the calls.
I want to provide an option to only lint on save.
@wingrunr21 Pointers on getting started on writing code for this (or any other current workaround) would be great too, thanks!
Rubber duck debugging here: the diagnostic requests are pushed from the server based on text changes. Instead of debouncing the linting calls themselves another option would be to have a configurable "cooldown" on running diagnostic calls. That would allow RxJS to interrupt the shell command earlier in the observable pipe. I'd need to do this just before the linter shell call (eg right before spawn) as I want to use the same infrastructure to keep other language diagnostics up to date in the future.
The easiest place to interrupt the lint based on configuration would be in Linter.ts
. The iif
call can be used to check configuration information.
The new configuration would need to be mapped in the SettingsCache
types. They should get pulled automatically though once they are defined in the extension configuration itself.
This is also happening to me. I'm hitting the following on a file that is 228 lines long that has about 22 errors:
Lint: executing rubocop -s /Users/username/project/lorem.rb -f json...
events.js:167
throw er; // Unhandled 'error' event
^
Error: write EPIPE
at WriteWrap.afterWrite [as oncomplete] (net.js:833:14)
Emitted 'error' event at:
at onwriteError (_stream_writable.js:431:12)
at onwrite (_stream_writable.js:456:5)
at _destroy (internal/streams/destroy.js:40:7)
at Socket._destroy (net.js:603:3)
at Socket.destroy (internal/streams/destroy.js:32:8)
at WriteWrap.afterWrite [as oncomplete] (net.js:835:10)
[Info - 3:24:39 PM] Connection to server got closed. Server will restart.
[Error - 3:24:39 PM] Request textDocument/foldingRange failed.
Error: Connection got disposed.
at Object.dispose (/Users/username/.vscode/extensions/rebornix.ruby-0.22.3/client/node_modules/vscode-jsonrpc/lib/main.js:876:25)
at Object.dispose (/Users/username/.vscode/extensions/rebornix.ruby-0.22.3/client/node_modules/vscode-languageclient/lib/client.js:71:35)
at LanguageClient.handleConnectionClosed (/Users/username/.vscode/extensions/rebornix.ruby-0.22.3/client/node_modules/vscode-languageclient/lib/client.js:2153:42)
at LanguageClient.handleConnectionClosed (/Users/username/.vscode/extensions/rebornix.ruby-0.22.3/client/node_modules/vscode-languageclient/lib/main.js:151:15)
at closeHandler (/Users/username/.vscode/extensions/rebornix.ruby-0.22.3/client/node_modules/vscode-languageclient/lib/client.js:2140:18)
at CallbackList.invoke (/Users/username/.vscode/extensions/rebornix.ruby-0.22.3/client/node_modules/vscode-jsonrpc/lib/events.js:62:39)
at Emitter.fire (/Users/username/.vscode/extensions/rebornix.ruby-0.22.3/client/node_modules/vscode-jsonrpc/lib/events.js:120:36)
at closeHandler (/Users/username/.vscode/extensions/rebornix.ruby-0.22.3/client/node_modules/vscode-jsonrpc/lib/main.js:226:26)
at CallbackList.invoke (/Users/username/.vscode/extensions/rebornix.ruby-0.22.3/client/node_modules/vscode-jsonrpc/lib/events.js:62:39)
at Emitter.fire (/Users/username/.vscode/extensions/rebornix.ruby-0.22.3/client/node_modules/vscode-jsonrpc/lib/events.js:120:36)
at IPCMessageReader.fireClose (/Users/username/.vscode/extensions/rebornix.ruby-0.22.3/client/node_modules/vscode-jsonrpc/lib/messageReader.js:111:27)
at ChildProcess.constructor.eventEmitter.on (/Users/username/.vscode/extensions/rebornix.ruby-0.22.3/client/node_modules/vscode-jsonrpc/lib/messageReader.js:213:45)
at ChildProcess.emit (events.js:187:15)
at maybeClose (internal/child_process.js:961:16)
at Socket.ChildProcess.spawn.stream.socket.on (internal/child_process.js:380:11)
at Socket.emit (events.js:182:13)
at Pipe.Socket._destroy._handle.close [as _onclose] (net.js:596:12)
[Info - 3:24:39 PM] Initializing Ruby language server...
[Info - 3:24:39 PM] Rebuilding tree-sitter for local Electron version
[Info - 3:24:39 PM] Rebuild succeeded!
vscode-ruby version: 0.22.3 Ruby version: 2.3.3p222 Ruby version manager (if any): rvm 1.29.3 VS Code version: 1.33.1 Operating System: Max OS X 10.14.2 (18C54) Using language server? Yes
To everyone watching this issue:
This is on my list. May has been an extremely busy month for me and I haven't gotten the chance to get this and a few other issues resolved. Thanks for your patience.
I hate to just chime in here, but I've run into this hard - on multiple projects with not extremely big or any errors, using standardrb for lint/format. I'm happy to help further debug or diagnose. Right now all the projects I'm working on are private so I can't provide exact details, but I can see if I can find an example.
FWIW, I'm also using the vim plugin.
By saying that
FWIW, I'm also using the vim plugin.
Do you mean ruby plugin for vim or vim plugin for vs code??
haha sorry, the vim plugin for vscode.
@wingrunr21 Any chance you could outline how you are thinking of solving this issue and e.g. relevant files to look in so others might be able to jump in and give it a go (i.e. me)?
Can you give v0.25.1 a try? The test file I created based on @shir's recommendation no longer crashes
@wingrunr21 looks like no more crashes for me 🎉! Thank you a lot!
@wingrunr21 I'm seeing no crashes on my main work project now 🎉.
Editing a Homebrew formula now crashes almost immediately, though:
Actually, no, after some restarts and opening the Homebrew stuff in the same project I don't see those crashes. Seems things are working fully for me now. The above crash is weird but avoidable for me.
I can also confirm that this doesn't happen anymore for me, with the latest version :) Awesome! Do you have an idea what fixed it, though?
I can also confirm that this doesn't happen anymore for me, with the latest version :) Awesome! Do you have an idea what fixed it, though?
I replaced the underlying spawn
implementation with one that was better situated to handle errors. Long story short is that if you spawn
a process in node and attempt to write to stdin
(like I am doing for all linters and formatters), in the event that spawn fails node throws an uncatchable EPIPE
. There's apparently no consistent way to detect a failed spawn other than setting error handlers on each of the std<in|out|err>
pipes.
I still plan on implementing lint on save. Probably do that in the next milestone as I implement remote environment support.
@wingrunr21 I'm seeing no crashes on my main work project now 🎉.
Editing a Homebrew formula now crashes almost immediately, though:
Well rats. I'll try and take a closer look. A specific formula or any formula?
Also looks like I need to ship source-map-support
so those stack traces are usable
Hi, I'm facing same issue in v0.27.0. how can i fix this issue?
Your environment
vscode-ruby
version: 0.22.3Expected behavior
Lint ruby files via rubocop without errors.
Actual behavior
Most time linter works as expected but on large files it may stop working. In output I see next message:
This error repeated several times and at the end
Usually, this happens on large files with a lot of issues and when I hard typing. After vscode restart, everything works ok for some time until I start to work with a large file again. At first, it shows all issues, and if I made minor changes then everything continues to work. But if I start again hard typing then is become fails.