Skip to content

Solve race conditions in unused_port #5267

Open
@michaelsproul

Description

@michaelsproul

Description

We've tried to rid our tests of the unused_port crate by preferring to bind on port 0, but there are still some circumstances where binding on a non-zero port is useful for testing, e.g.

The unused_port crate as currently written is inherently racy because it doesn't keep state across processes, i.e. there can be a small delay between a process allocating a "free" port, and starting the service to listen on that port. During this delay, another process can leap in, allocate the same port, and start a service which will cause the original process's service to fail to start.

Steps to resolve

Option 1: On-disk database

One option for sharing state would be to use an on-disk database at a static location (e.g. /tmp/lighthouse-ports.sqlite). I think using a lightweight database like sqlite might be easiest, as it would let us outsource some of the consistency & locking logic. Alternatively we could roll our own file-locking, but this would also require defining an on-disk format (SSZ of Vec<u16>?)

Option 2: Pass sockets

A slightly cleaner but less versatile solution than the on-disk DB would be to bind a socket on port 0, and hold onto it. If we could pass an already listening socket to libp2p, our HTTP library or whatever other listening service, then this would avoid the raciness of allocating the port, releasing it, and then re-binding it. However this approach will not work for external processes used in tests (like the dummy eth1 node, or web3signer).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions