Skip to content

[Floci] Service Bus host ports are probed then released, so another process can take them before the Artemis sidecar binds #2335

Open

Description

@thomhurst

Describe the bug

When WithServiceBus() is called without explicit ports, FlociServiceBusEndpointAllocator picks the AMQP and AMQPS host ports itself during BeforeStartEvent. It binds a probe TcpListener on each candidate port, releases the probes, and passes the ports to floci-az through FLOCI_AZ_SERVICES_SERVICE_BUS_AMQP_PORT and FLOCI_AZ_SERVICES_SERVICE_BUS_AMQP_TLS_PORT. floci-az binds them much later, when it starts the Artemis sidecar with -p <port>:5672 and -p <port>:5671.

Nothing holds the port between the release and Docker's bind. That window covers the rest of AppHost startup, the floci-az image pull, and floci-az's own boot, so it is often several seconds long. Any other process can take the port in that time: another AppHost started concurrently with --isolated, a DCP proxy, a test fixture, or anything else that binds a port. Docker then fails to start the sidecar:

failed to bind host port 0.0.0.0:<port>/tcp: address already in use

floci-az logs the failed namespace start and reports /health as DOWN, so the emulator never becomes healthy and every Service Bus consumer waits forever. Docker retries a port conflict only for dynamic (0) host ports, so an explicit preselected port cannot recover.

#2240 / #2241 moved the selection to a random port in 20000-32767 so DCP's ephemeral proxy ports no longer collide with it. That removed the most common collision, but the allocator still probes and releases, so the time-of-check/time-of-use race remains for everything else that binds ports in that range, including a second AppHost making the same random choice.

Regression

Not a regression. The probe-and-release design has been in place since the allocator was added in 13.6.0.

Steps to reproduce

The race is timing-dependent, so the simplest deterministic repro takes the selected port between allocation and the sidecar's start, as another process would:

var builder = DistributedApplication.CreateBuilder(args);

var azure = builder.AddFlociAzure("floci-az").WithDockerSocket();
var serviceBus = azure.WithServiceBus();

// Simulate another process binding the port after the integration released it.
TcpListener? squatter = null;
builder.Eventing.Subscribe<BeforeResourceStartedEvent>(azure.Resource, (_, _) =>
{
    squatter ??= new TcpListener(IPAddress.Any, serviceBus.Resource.AmqpEndpoint.Port);
    squatter.Start();
    return Task.CompletedTask;
});

builder.Build().Run();
  1. Run the AppHost.
  2. floci-az logs that it could not start the default Service Bus namespace because Docker could not bind the host port.
  3. floci-az stays Unhealthy, and anything that waits for it never starts.

Without the squatter, the same failure happens intermittently when several AppHosts start at the same time on one machine (for example parallel CI jobs or test fixtures), or when another local service happens to bind the selected port first.

Expected behavior

The Service Bus sidecar starts reliably regardless of what else binds ports on the machine. Only an atomic bind can guarantee that, so the host ports should be assigned by Docker, not chosen in advance by the integration:

  1. When the caller does not pass amqpPort / amqpTlsPort, set FLOCI_AZ_SERVICES_SERVICE_BUS_AMQP_PORT=0 and FLOCI_AZ_SERVICES_SERVICE_BUS_AMQP_TLS_PORT=0. floci-az already treats 0 as a dynamic Docker binding.
  2. Leave the child's amqp / amqps endpoints unallocated until floci-az is ready, then read the ports Docker published from floci-az's management API (GET /{account}-servicebus/namespaces/default, fields amqpHostPort / amqpsHostPort), allocate the endpoints, and raise ResourceEndpointsAllocatedEvent and ConnectionStringAvailableEvent for the child.
  3. Keep explicitly configured ports exactly as they are today.

Two details matter for this:

Screenshots

N/A

IDE and version

Other

IDE version

Aspire CLI / Aspire.AppHost.Sdk 13.6.4

Nuget packages

CommunityToolkit.Aspire.Hosting.Floci (current main)
Image: floci/floci-az:0.15.0
Docker Desktop on Windows 11; also Linux CI runners

Additional context

Related: #2240, #2241.

Help us help you

Yes, I'd like to be assigned to work on this item

Activity

  1. added a commit that references this issue on Nov 1, 2026
    7ba4351
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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