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

Docker image rcjsuen/docker-langserver exits abruptly 3 seconds after starting #271

Open
Nexion opened this issue Jan 8, 2025 · 2 comments

Comments

@Nexion
Copy link

Nexion commented Jan 8, 2025

Expected behavior:
Emacs LSP client package lsp-mode runs docker-langserver executable with --stdio argument. It works well with docker-language-server installed on the same host, but there's an issue if you instead try to use the official docker image.

Wrapper script to execute the server in a container:

#!/bin/bash

exec podman run -i --rm --network=none rcjsuen/docker-langserver:latest "$@"

What's wrong:
On opening a file of Dockerfile format in Emacs the container successfully starts, LSP client and server begin message exchange, but 3 seconds later the container shuts down with exit code 1 without any visible reason.

Why:
Running the container with exit trace shows that the issue happens in vscode-languageserver dependency code.

podman run -i --rm --entrypoint='["sh", "-c", "node --trace-exit lib/server.js --stdio"]' rcjsuen/docker-langserver:latest "$@" 2>/tmp/stderr.log

stderr.log:

(node:1) WARNING: Exited the environment with code 1
    at exit (node:internal/process/per_thread:187:13)
    at /docker-langserver/node_modules/vscode-languageserver/lib/node/main.js:101:29
    at listOnTimeout (node:internal/timers:573:17)
    at processTimers (node:internal/timers:514:7)

Corresponding code in node_modules/vscode-languageserver/lib/node/main.js:

const watchDog = {
    initialize: (params) => {
        const processId = params.processId;
        if (Is.number(processId) && exitTimer === undefined) {
            // We received a parent process id. Set up a timer to periodically check
            // if the parent is still alive.
            setInterval(() => {
                try {
                    process.kill(processId, 0);
                }
                catch (ex) {
                    // Parent process doesn't exist anymore. Exit the server.
                    process.exit(_shutdownReceived ? 0 : 1);
                }
            }, 3000);
        }
    },
    get shutdownReceived() {
        return _shutdownReceived;
    },
    set shutdownReceived(value) {
        _shutdownReceived = value;
    },
    exit: (code) => {
        endProtocolConnection();
        process.exit(code);
    }
};

So as it turns out, an LSP client sends its PID as processId within its first initialization request message to server, and the server code checks if that PID is still alive with a 3000ms interval, but obviously can't find that PID within a container namespace. Guess this check has to be turned off in the docker image.

@rcjsuen
Copy link
Owner

rcjsuen commented Jan 9, 2025

@Nexion Very interesting. Thank you for the bug report. I wonder if this is worth mentioning in the microsoft/vscode-languageserver-node repository for visibility?

@Nexion
Copy link
Author

Nexion commented Jan 12, 2025

@rcjsuen The only other LSP server written in typescript that I'm also using is bash-language-server and I had the same issue trying to run the latest release in a container. They don't publish their own official image though.

Now that you asked about that library, I suddenly noticed this code and gotta say that running the server in a container with --clientProcessId 1 does the magic, the watchdog ignores the PID provided by the client during session initialization.

Guess that solves the issue — but I know very little about the subject, so if you don't consider it a reliable workaround then maybe it's worth mentioning.

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

2 participants