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 support broken on Windows? #644

Closed
observant2 opened this issue Jun 25, 2020 · 13 comments
Closed

stdio support broken on Windows? #644

observant2 opened this issue Jun 25, 2020 · 13 comments
Labels
info-needed Issue requires more information from poster

Comments

@observant2
Copy link

I have the following code that executes my language server and uses stdio as TransportKind:
https://github.com/itmuckel/factor-lsp/blob/master/lsp-sample/client/src/extension.ts

        let serverOptions: ServerOptions = {
		command: "C:/factor/factor-lsp/factor-lsp.exe",
		transport: TransportKind.stdio,
	};

	// Options to control the language client
	let clientOptions: LanguageClientOptions = {
		// Register the server for plain text documents
		documentSelector: [{ scheme: 'file', language: 'Factor' }],
		synchronize: {
			// Notify the server about file changes to '.clientrc files contained in the workspace
			fileEvents: workspace.createFileSystemWatcher('**/.clientrc')
		}
	};

	// Create the language client and start the client.
	client = new LanguageClient(
		'languageServerExample',
		'Language Server Example',
		serverOptions,
		clientOptions
	);

	// Start the client. This will also launch the server
	client.start();

This works on Linux (Ubuntu). My LS gets the "initialize" and "shutdown" requests, but no responses come back from it.
On Windows my LS won't even get the requests from the Client.

Anyone else experienced this and/or have some ideas how to fix this? 🤔

@dbaeumer
Copy link
Member

I just tested this under Windows with my test bed in this repository and it worked without any problems. What makes stdio very flaky is that fact that the server can't log anything to stdio. Otherwise the communication will fail.

@dbaeumer
Copy link
Member

Does the LSP sample work for you under Windows using stdio. https://github.com/microsoft/vscode-extension-samples/tree/master/lsp-sample

@dbaeumer dbaeumer added the info-needed Issue requires more information from poster label Jun 26, 2020
@observant2
Copy link
Author

Yes, that seems to work.

The problem is that when I output some debug information to a file, I see that my server has trouble reading the content-length.

It just reads a line, strips it from "Content-Length: ", trims and parses the number, but at this point it already fails. The weird thing is that on linux it worked without problems.

It is especially no node server, just a plain executable that will be started. Maybe that changes things? Surely this lib does different stuff, when running a node server than executing a child process.

To rule out that the programming language I use messes it up, I wrote a C# console app like this:

using System;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            using (System.IO.StreamWriter file =
                new System.IO.StreamWriter(@"C:\Users\Admin\Documents\lsp.txt", true))
            {
                while (true)
                {
                    file.WriteLine(Console.ReadLine());
                }
            }
        }
    }
}

The file is created, but remains empty. On Linux the same experiment showed me the requests that the client would send to my server. Does this work on your system?

@observant2
Copy link
Author

This code works. I still don't know why I need to do this in order to read the input from the client.

using System;
using System.IO;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var read = new BinaryReader(Console.OpenStandardInput());
            
            using var file =
                new System.IO.StreamWriter(@"C:\Users\Admin\Documents\lsp.txt", true);
            while (true)
            {
                file.WriteLine(read.ReadChar());
            }
        }
    }
}

@dbaeumer
Copy link
Member

@itmuckel is there anything you need from my end. I am not a C/C++ expert.

@bostick
Copy link

bostick commented Jun 30, 2020

I am also running into issues with stdio on Windows. I am developing language server and it runs fine on Mac and Linux. However on Windows, there are all sorts of trouble. It is very strange because my language server runs fine on Windows under Sublime. But it does not work with VSCode.

The problem manifests itself as a hang. The initial traffic from VSCode to the server is in the Output window, and that is all that happens. It seems that the server is waiting on input.

I am trying to dig down and investigate how VSCode launches child processes and sets up stdin, stdout, and stderr on Windows. It seems like there is some difference between Sublime and VSCode that is significant. I'm afraid I don't know much about Windows processes, inheriting handles, console vs. GUI apps, etc.

@dbaeumer
Copy link
Member

dbaeumer commented Jul 1, 2020

@bostick please let me know what you find out.

@bostick
Copy link

bostick commented Jul 2, 2020

I have an update of sorts...

I'm trying to create a language server for Wolfram Engine. On Windows, there is both a WolframKernel.exe GUI app and a wolfram.exe console app.

Intuitively I was using the console app and it was not working (as described above). The crazy thing is that using GUI app does work!

I am able to have a working language server on Windows by using the GUI app version but not the console app. I do not quite understand why this is the case and I wish debugging this sort of thing was easier.

So that's all good news, though inexplicable.

@dbaeumer
Copy link
Member

dbaeumer commented Jul 3, 2020

@bostick to our knowledge this is something specific to Windows. Somehow when you link a Windows executable you can decide how it will deal with stdio. We saw other cases were a parent process couldn't read from stdio from client processes.

@observant2
Copy link
Author

@dbaeumer Can you expand on this? How can you decide how it will deal with stdio? This might be exactly the problem bostick and I are facing.

@dbaeumer
Copy link
Member

dbaeumer commented Jul 6, 2020

The one the generates the executable (e.g. links it if it is a C++ application) seems to have an influence on it. But I am not an expert with C++ under Windows so I don't exactly know how this works.

@vscodebot
Copy link

vscodebot bot commented Jul 13, 2020

This issue has been closed automatically because it needs more information and has not had recent activity. See also our issue reporting guidelines.

Happy Coding!

@vscodebot vscodebot bot closed this as completed Jul 13, 2020
@xietuo
Copy link

xietuo commented Aug 5, 2020

@dbaeumer
This issue may be related to this phenomenon.
I wrote a C program.

#include <stdio.h>
int main() {
   printf("test\n");
   return 0;
}

And I wrote a nodejs program to call this C program.

var cp = require('child_process');
var child = cp.spawn("a.exe");
child.stdout.on('data', function (data) {
    console.log(data);
});

when i get stdout output, \n characters will be replaced with \r\n

(0d 0a) means \r\n
image

PS D:\Code> node index.js
<Buffer 74 65 73 74 0d 0a>

The same problem occurs in vscode extension.

image

LSP Message The header part includes the ‘\r\n’ separating the header and content part. When \n is converted to \r\n, the original \r\n is changed to \r\r\n. As a result, the format is incorrect, and the connection using the stdio process fails.

I don't know why this happened, but it seems to be related to this issue. Can someone please explain it to me?

@vscodebot vscodebot bot locked and limited conversation to collaborators Aug 27, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
info-needed Issue requires more information from poster
Projects
None yet
Development

No branches or pull requests

4 participants