Skip to content

libtest: ports obtained via get_free_port() for secondary/auxiliary uses are never released #474

Description

@p-alik

Background

#471 / #472 fixed the primary port-reservation race in libtest::Server::start(): get_free_port() now keeps its reservation socket bound until the caller explicitly calls release_port(), and Server::start() releases its own _port once the server is confirmed up (or definitively failed) via an RAII guard.

That fix only releases the Server object's own _port. Several call sites use get_free_port() to reserve a port for something other than the Server's primary port — e.g.:

  • tests/httpd_test.cc:149http_port is reserved and passed as --http-port= to a gearmand instance whose Server::_port is actually default_port(). The Server never knows about http_port, so its reservation is never released.
  • tests/gearmand.cc:190,549 (long_keepalive_start_TEST, config_file_SIMPLE_TEST) — ports reserved via get_free_port() for --check-args runs that don't go through a Server object at all.

In all of these, the reservation socket now stays open (bound, unreleased) for the remaining lifetime of the test process instead of being freed once it's no longer needed.

Impact

Low severity — this does not reintroduce the original race (holding a reservation longer than necessary is safe, just wasteful). The practical effect is a growing number of open file descriptors / permanently-occupied ephemeral ports for the rest of a given test binary's run. Unlikely to cause failures on its own, but wastes resources and could compound in long-running or -j-parallel test invocations.

Suggested fix

Give these call sites an explicit release_port(port) once the port is no longer needed (e.g. after the associated server/process is confirmed started, or via a scoped RAII guard similar to the one added in Server::start()). Would need to audit all get_free_port() call sites under tests/ to find which ones aren't already covered by a Server::start()/release_port() pair.

References

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions