Skip to content

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

@Nexion

Description

@Nexion

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions