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

Stdio isn't working with NeoVim v0.4.0 in Windows #499

Closed
lucas-miranda opened this issue Aug 18, 2019 · 25 comments
Closed

Stdio isn't working with NeoVim v0.4.0 in Windows #499

lucas-miranda opened this issue Aug 18, 2019 · 25 comments

Comments

@lucas-miranda
Copy link

I tried everything and can't make OmniSharp with stdio works, server starts normally, log data seems okay, but it stays still, don't showing any error or executing commands.
But all works fine with http.

Setup:

  • NeoVim 0.4.0 (Running with NeoVim-Qt)
  • Windows 10
  • I'm not using WSL to run vim
@nickspoons
Copy link
Member

Hi @lucas-miranda, thanks for opening this issue.

Yes there is something neovim in Windows that doesn't work - both terminal and nvim-qt. It starts the server and sends requests, but never receives responses - I have tried debugging the server but breakpoints are never hit.

I really don't know if this is a Windows neovim bug, or if we're doing something wrong (works in Linux though..?).

The issue is discussed in #468, and in this comment you can find a link to little proxy program. If you build it and then point g:OmniSharp_server_path to the exe, it should work.

Note that this is a workaround, not a solution, I've just been looking at this again recently and am hoping we can get it resolved.

@jpfeiffer16
Copy link
Contributor

Just poking my head in here since I found this for your slack message @nickspoons.
I haven't really done anything looking at this issue since I last messaged you, but I do think it might be worth noting that I found it interesting recently when looking at the proc tree of VSCode on windows, that it spawns a cmd proc with /c that then spins up the omnisharp server.

May be worth a try to see if that works for neovim on widows as well.

@nickspoons
Copy link
Member

nickspoons commented Sep 17, 2019

Thanks @jpfeiffer16, I tried starting the server in various ways with cmd.exe wrappers etc., but had no luck.

After further experimentation, I've found that neovim can't communicate directly with .NET Framework executables.The following program receives and returns messages to neovim when compiled as a .NET core project, but not as a .NET framework project:

using System;

public class Program {
   public static void Main() {
      Console.WriteLine("Started server");

      var line = Console.ReadLine();
      while (!string.IsNullOrEmpty(line)) {
         Console.WriteLine($"We received {line}");
         line = Console.ReadLine();
      }
   }
}

The .NET Framework program never receives anything from Console.ReadLine(). I believe compiling @jpfeiffer16's stdioproxy program as .NET Framework also does not work.

At this stage I'm not sure there's any benefit in investigating further. I don't know if the error is with neovim or with the .NET Framework. Anyone wanting to use neovim with OmniSharp-vim in Windows can use the .NET core stdioproxy as a wrapper around OmniSharp-vim.

This situation is, obviously, not entirely satisfactory.

@nickspoons
Copy link
Member

For anyone interested, here's the vim script I've been using to test calling the above program:

function! NeovimOutHandler(job_id, data, event) dict abort
  let messages = a:data[:-2]

  if exists('g:job')
    if len(a:data) > 1
      let messages[0] = g:job.partial . messages[0]
      let g:job.partial = a:data[-1]
    else
      let g:job.partial = g:job.partial . a:data[0]
    endif
  endif

  for message in messages
    if message =~# "^\uFEFF"
      " Strip BOM
      let message = substitute(message, "^\uFEFF", '', '')
    endif
    echohl Identifier | echom message | echohl None
  endfor
endfunction

function! NeovimJobStart() abort
  let opts = { 'on_stdout': 'NeovimOutHandler' }
  let g:job = {
  \ 'job_id': jobstart('bin\Debug\simpleio.exe', opts),
  \ 'partial': ''
  \}
endfunction





function! VimOutHandler(channel, message) abort
  echohl Identifier | echom a:message | echohl None
endfunction

function! VimJobStart() abort
  let opts = { 'out_cb': 'VimOutHandler' }
  let g:job = {
  \ 'job_id': job_start('bin\Debug\simpleio.exe', opts)
  \}
endfunction




function! SendMessage(message) abort
  if has('nvim')
    call chansend(g:job.job_id, a:message . "\n")
  else
    call ch_sendraw(g:job.job_id, a:message . "\n")
  endif
endfunction
command! -nargs=+ SendMessage call SendMessage(<q-args>)

function! StartServer() abort
  if exists('g:job')
    echo 'A server is already running'
    return
  endif
  if has('nvim')
    echom 'Starting for Neovim'
    call NeovimJobStart()
  else
    echom 'Starting for Vim'
    call VimJobStart()
  endif
endfunction
command! StartServer call StartServer()


function! StopServer() abort
  if !exists('g:job')
    echo 'No server running'
    return
  endif
  if has('nvim')
    call jobstop(g:job.job_id)
  else
    call job_stop(g:job.job_id)
  endif
  unlet g:job
  echom 'Server stopped'
endfunction
command! StopServer call StopServer()

@lucabol
Copy link

lucabol commented Oct 25, 2019

fyi I am using the proxy script referenced here to work around this problem (modified to run on Windows). Most things work, except from "ALE". I think it is because the python script goes directly to the OmniSharp server instead of going to the Proxy. I didn't find an obvious point in the code to fix that. Also, it is just my guess ...

@nickspoons
Copy link
Member

Hmm, I don't think that is the reason - ALE is handled completely differently in stdio mode, and the python/ale_lint.py script should never be loaded (line 5 of ale_linters/cs/omnisharp.vim exits early in stdio mode, and this is the file which loads ale_lint.py).

In stdio, the ALE autocmd ALEWantResults is triggered (see plugin/OmniSharp.vim line 102), and the function that is called only runs in stdio mode. This all runs like other async requests, so I don't know why it's failing for you.

It's a tricky thing to debug too (remembering getting ALE working with stdio in the first place), because the autocmd is executed by ALE with :silent, so any :echomsg commands you sprinkle through will be ignored. If you want to try it, remove the silent from ALE autoload/ale.vim line 113:

    silent doautocmd <nomodeline> User ALEWantResults

@lucabol
Copy link

lucabol commented Oct 25, 2019

Looking at it a bit more. Running ALEInfo it seems that the OmniSharp linter is not enabled, despite being in the ale_linters dictionary and the file being recognized as cs.

Current Filetype: cs
Available Linters: ['csc', 'mcs', 'mcsc']
Enabled Linters: []
... other settings ...
g:ale_linter_aliases = {}
let g:ale_linters = {'cs': ['OmniSharp']}

@nickspoons
Copy link
Member

@lucabol that is expected - it's a side-effect of using the ALEWantResults autocmd, instead of letting ALE have complete control.

@lucabol
Copy link

lucabol commented Oct 25, 2019

I see. Thx. I have removed silent from ale.vim as you suggested above. What should I do debug this more? Sorry, I am new to Vim and Omnisharp ...

@nickspoons
Copy link
Member

@lucabol I was just thinking of tracing the execution by adding echomsg 'here I am' through the code, from the s:ALEWantResults() function initially called by ALE, to ale#sources#OmniSharp#WantResults() to OmniSharp#stdio#CodeCheck() etc. Nothing like good old Console.WriteLine("made it this far") debugging :)

My laptop is about to run flat so I'm going to hit the hay, good luck!

@lucabol
Copy link

lucabol commented Oct 25, 2019

@nickspoons everything in the 'augroup OmniSharp#Integrations' starting on line 99 is executed correctly. I put an echomsg after each statement and saw them all when opening nvim.

@nickspoons
Copy link
Member

@lucabol the question is whether the s:ALEWantResults() function is getting called

@lucabol
Copy link

lucabol commented Oct 25, 2019

Yes, it is as the echomsg after it gets printed.

@Laptop765
Copy link
Contributor

Just curious, has anyone opened this issue in the Neovim repository in case it's a bug on their end?

@jpfeiffer16
Copy link
Contributor

I did at one point debug the neovim codebase trying to find the issue. I localized it to the way libuv interacts with the stdout stream of .net process. However I don't have the c skills to figure anything out beyond that and so am not sure if it's .net side or neovim/libuv side. I never opened an issue because I found a workaround by proxying stdio between the two processes and it only happens on windows.

@Laptop765
Copy link
Contributor

Is it worth running by either or both of them to take a look so it can be fixed?

@nickspoons
Copy link
Member

Yeah I always meant to open a neovim issue but it's really hard to create something reproducible enough to be a valid issue. The repro project I described above is probably as good as we can get though, so yes it would be a good idea. It's even quite possible that there are just some different flags we should be sending to neovim?

I'll try to get around to it, very time-poor at the moment unfortunately.

@nickspoons
Copy link
Member

I have opened neovim issue #11809 - let's hope someone on that side can shed some light on the issue.

@jpfeiffer16 if you have anything to add there after your debugging attempts, that would be very helpful.

@jpfeiffer16
Copy link
Contributor

Thanks @nickspoons ! I put a comment on that issue.

@nickspoons nickspoons changed the title Stdio isn't working with NeoVim v0.4.0 Stdio isn't working with NeoVim v0.4.0 in Windows Jun 8, 2020
@nickspoons
Copy link
Member

Just to follow up on this, there is a neovim bug here, as described in the issue linked above. There is a neovim PR which should resolve it, currently marked as a neovim 0.5 milestone, so hopefully not too far away.

@nickspoons
Copy link
Member

The neovim PR has been merged, and is available to Windows users in the nightly builds! I have tested it and it works now.

I have therefore closed this issue, and added a note to the README about the neovim issue.

@jpfeiffer16
Copy link
Contributor

Awesome. Thanks for your work on tracking this down @nickspoons !

@nickspoons
Copy link
Member

You too, @jpfeiffer16, your proxy was integral in getting it found and fixed.

@nickspoons
Copy link
Member

Where's the :pat-each-other-on-the-back: emoji...?

@jpfeiffer16
Copy link
Contributor

Haha! Happy to have contributed! Thank you for working with the NeoVim org to track it down and crushing it.

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

5 participants