Skip to content

The 'curl -s' command seems to always return True under curl 7.81.0, preventing 'qlever start' from working properly. #218

@BaoYuheng

Description

@BaoYuheng

I'm trying to deploy the qlever server locally, but I keep encountering a bug: no matter how I change the port number, qlever start always shows QLever server already running on ....:port.

I checked qlever-control's source code, and I seem to have found the issue:
For my curl version:
curl 7.81.0 (x86_64-pc-linux-gnu) libcurl/7.81.0 OpenSSL/3.0.2 zlib/1.2.11 brotli/1.0.9 zstd/1.4.8 libidn2/2.3.2 libpsl/0.21.0 (+libidn2/2.3.2) libssh/0.9.6/openssl/zlib nghttp2/1.43.0 librtmp/2.3 OpenLDAP/2.5.16 Release-Date: 2022-01-05

The following function (I've extracted a portion, which should be in start.py and util.py) always returns QLever server already running on ...., even though I have confirmed via lsof that there is no process using that port.

import errno
import re
import secrets
import shlex
import shutil
import socket
import string
import subprocess
from datetime import date, datetime
from pathlib import Path
from typing import Any, Optional




def run_command(
    cmd: str,
    return_output: bool = False,
    show_output: bool = False,
    show_stderr: bool = False,
    use_popen: bool = False,
) -> Optional[str | subprocess.Popen]:
    """
    Run the given command and throw an exception if the exit code is non-zero.
    If `return_output` is `True`, return what the command wrote to `stdout`.

    NOTE: The `set -o pipefail` ensures that the exit code of the command is
    non-zero if any part of the pipeline fails (not just the last part).

    TODO: Find the executable for `bash` in `__init__.py`.
    """

    subprocess_args = {
        "executable": shutil.which("bash"),
        "shell": True,
        "text": True,
        "stdout": None if show_output else subprocess.PIPE,
        "stderr": None if show_stderr else subprocess.PIPE,
    }

    # With `Popen`, the command runs in the current shell and a process object
    # is returned (which can be used, e.g., to kill the process).
    if use_popen:
        if return_output:
            raise Exception("Cannot return output if `use_popen` is `True`")
        return subprocess.Popen(f"set -o pipefail; {cmd}", **subprocess_args)

    # With `run`, the command runs in a subshell and the output is captured.
    result = subprocess.run(f"set -o pipefail; {cmd}", **subprocess_args)

    # If the exit code is non-zero, throw an exception. If something was
    # written to `stderr`, use that as the exception message. Otherwise, use a
    # generic message (which is also what `subprocess.run` does with
    # `check=True`).
    if result.returncode != 0:
        if len(result.stderr) > 0:
            raise Exception(result.stderr.replace("\n", " ").strip())
        else:
            raise Exception(
                f"Command failed with exit code {result.returncode}, "
                f" nothing written to stderr"
            )
    # Optionally, return what was written to `stdout`.
    if return_output:
        return result.stdout


def is_qlever_server_alive(endpoint_url: str) -> bool:
    """
    Helper function that checks if a QLever server is running on the given
    endpoint. Return `True` if the server is alive, `False` otherwise.
    """

    message = "from the `qlever` CLI"
    curl_cmd = (
        f"curl -s {endpoint_url}/ping"
        f" --data-urlencode msg={shlex.quote(message)}"
    )
    try:
        run_command(curl_cmd)
        return True
    except Exception:
        return False

def if_alive(endpoint_url):
    if is_qlever_server_alive(endpoint_url):
        print(f"QLever server already running on {endpoint_url}")
        print("")
        print(
            "To kill the existing server, use `qlever stop` "
            "or `qlever start` with option "
            "--kill-existing-with-same-port`"
        )

        # Show output of status command.
        return False
    
if __name__ == "__main__":
    if_alive('localhost:5673') #have tried different ports, reproducing the issue

Could this be caused by a curl version issue?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions