Repository: ycm-core/ycmd

Issue:
Always open a pipe to stdin for the tern command
The Tern command exits when its stdin closes. If no stdin is provided,
it exits immediately, so we have to provide a stdin to keep it running.

This caused tern to exit right after it was started by YouCompleteMe. I'm a bit curious to why no one else seem to have this problem.

<!-- Reviewable:start -->

---

This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/valloric/ycmd/450)

<!-- Reviewable:end -->



Discussion:
I think this will break windows support. 

Tern just added a --ignore-stdin flag which we should probably use instead. 

[![Coverage Status](https://coveralls.io/builds/5656684/badge)](https://coveralls.io/builds/5656684)

Coverage remained the same at 84.534% when pulling **167c2fcbf72e51631d654799afcd9289a28eba77 on trygveaa:tern-always-open-stdin** into **09f216441f99c02d51f9460e006683c5fe83669e on Valloric:master**.

The only thing `stdin_windows` does is set `stdin` to `PIPE` if `stdin_windows` is `PIPE` and it is running on Windows. So this should not change the behavior for Windows. Why do you think it will break?

I could add `--ignore-stdin` instead, but then I think both `stdin` and `stdin_windows` should be removed. Otherwise, the code would be pretty confusing IMO. If this is done, someone will have to verify that it still works on Windows.

thanks for the explanation. 

Well fortunately we have CI to show if Windows support works and it looks like it does :) 

I too am curious as to why we have not seen this in testing on other platforms. 

In What scenario did you find the issue?

Aha, the error only occurs when running ycmd with python 3. When running it with python 3, tern is run with `stdin` pointed at `/dev/null`. When running it with python 2, `stdin` is pointed at the same place as ycmds `stdin`, which is a pipe, so then it works.

I guess most people run it with python 2, so that's probably why no one else has reported the bug.

Not sure why that happens with python 3 though. The docs for both python 2 and 3 says regarding the `stdin` argument of `Popen`:

> With the default settings of None, no redirection will occur; the child’s file handles will be inherited from the parent.

Regarding the scenario I experience the issue, I just installed YouCompleteMe with Vundle, ran `./install.py --tern-completer`, put `let g:ycm_server_python_interpreter = '/usr/bin/python'` in my vim config and opened a javascript file in vim.

Thanks so much for the additional info. It's still strange - our CI tests run fine on Python 3. 

Just to be clear I'm not against merging this (thanks for doing it!). I just like to fully understand _why_ it fixes it :)

I still don't feel I fully understand it :/

Are you sure that the tests cover this?

I could run the tests locally without this patch and see if they fail here (just would have to set up a test environment first, didn't bother for this small change before, since CI runs the tests).

If so, I'm not sure what could be the reason. For info, I'm running Arch Linux with python 3.5.1.

Well. If the tern server didn't start in our tests, then all the JavaScript tests would fail.

I tried running the tests for the javascript completer on my machine with python 3 now. They all passed. Maybe tern is started in some other way in the tests?

The issue only happens starting with Python 3.4. I tested it using the example client.

> Maybe tern is started in some other way in the tests?

No but the ycmd server is not started. This has something to do with the Tern server running inside the ycmd process.

---

Reviewed 1 of 1 files at r1.
Review status: all files reviewed at latest revision, 1 unresolved discussion.

---

_[ycmd/completers/javascript/tern_completer.py, line 401 [r1]](https://reviewable.io:443/reviews/valloric/ycmd/450#-KFTZ4PMeoV5eQv2aQgM:-KFTZ4PMeoV5eQv2aQgN:-400513172) ([raw file](https://github.com/valloric/ycmd/blob/167c2fcbf72e51631d654799afcd9289a28eba77/ycmd/completers/javascript/tern_completer.py#L401)):_
We need to add a note that it happens starting with Python 3.4.

---

_Comments from [Reviewable](https://reviewable.io:443/reviews/valloric/ycmd/450#-:-KEX_E63dC8FRZooqvoq:1085123692)_

<!-- Sent from Reviewable.io -->


Resolving patch:
diff --git a/ycmd/completers/javascript/tern_completer.py b/ycmd/completers/javascript/tern_completer.py
--- a/ycmd/completers/javascript/tern_completer.py
+++ b/ycmd/completers/javascript/tern_completer.py
@@ -404,12 +404,14 @@ def _StartServerNoLock( self ):
           port = self._server_port,
           std = 'stderr' )
 
-      # On Windows, we need to open a pipe to stdin to prevent Tern crashing
-      # with following error: "Implement me. Unknown stdin file type!"
+      # We need to open a pipe to stdin or the Tern server is killed.
+      # See https://github.com/ternjs/tern/issues/740#issuecomment-203979749
+      # For unknown reasons, this is only needed on Windows and for Python 3.4+
+      # on other platforms.
       with utils.OpenForStdHandle( self._server_stdout ) as stdout:
         with utils.OpenForStdHandle( self._server_stderr ) as stderr:
           self._server_handle = utils.SafePopen( command,
-                                                 stdin_windows = PIPE,
+                                                 stdin = PIPE,
                                                  stdout = stdout,
                                                  stderr = stderr )
     except Exception:


Test patch: