site serve: report a port that something else holds as taken, and start nothing #252

Closed
opened 2026-09-29 02:25:29 +01:00 by allod-agent · 0 comments
Member

Make allod site serve refuse to start a preview on a port that something else already holds, so it never prints another program's address as the site's own.

Primary goals:

  • A held port is reported as taken — when something already answers on the site's port, serve exits 1, names the port, and starts nothing.
  • The registry stays the only source of a port — a site is served on its preview_port, or on --port, and on nothing else. A site with neither is refused as it is today.
  • Nothing else changes — a site whose port is free is started with the same command as before, and --stop and view are untouched.

Current state

Observed on a dev VM, with another process listening on the site's port before the start, for three apps (zola, live-server, Vite with --strictPort):

$ allod site serve
http://127.0.0.1:<port>
$ echo $?
0

The unit's journal for the same start, live-server's case:

ERROR live_server::http_layer::listener] Address 127.0.0.1:<port> is already in use
allod-preview-<slug>.service: Failed with result 'exit-code'.

Each app failed as its contract requires. serve had already returned: sitePreviewWait (cmd/allod/site_serve.go:201, at ef380c8) takes a connection to the port as good news while the unit is up, and the unit is still up while nix run is evaluating, before the app has tried to bind. The address printed is the other process's.

docs/allod-site-preview.md:10 describes this case as reported "as serving".

Default

Before starting a unit that is not running (cmd/allod/site_serve.go:114), serve connects to the port once. An answer means the port is taken: exit 1, a message naming the port and the unit that was not started, and no systemd-run. The check comes after the checks of the checkout path and the flake's preview app, so a fault in the site is reported before a port that is only busy for now.

A unit that is already running is not checked: finding the site's own preview up is the ordinary case and still prints its address.

What this leaves open

Another process can take the port in the seconds between the check and the app's bind, while nix run evaluates. serve would then print the address with exit 0 while the unit's journal shows the app failing. With a port the owner assigned in the registry, which nothing else is aiming for, this is rare. Closing it means confirming that the listening socket belongs to a process of the unit, which was built and measured under allod/tools#249 and costs about a hundred lines that read kernel files. It is a follow-up only if the case is seen in use.

Validation

  • A port held by another process, from the registry and from --port: exit 1, the port named, no address printed, no unit started.
  • A site with a registry port, and one given --port, on a free port: started with the same systemd-run arguments as before.
  • A second serve while the preview is running: the address, exit 0.
  • A site with no port: refused as today.

Scope

In: the check before a start in serve, its message, its tests, the contract bullet in docs/allod-site-preview.md, and the exit-code line of serve --help. Out: picking a port for a site that has none, and view learning a port from the VM, both dropped with allod/tools#249; which registry a dev VM reads, allod/archetypes#119.

Make `allod site serve` refuse to start a preview on a port that something else already holds, so it never prints another program's address as the site's own. Primary goals: - **A held port is reported as taken** — when something already answers on the site's port, `serve` exits 1, names the port, and starts nothing. - **The registry stays the only source of a port** — a site is served on its `preview_port`, or on `--port`, and on nothing else. A site with neither is refused as it is today. - **Nothing else changes** — a site whose port is free is started with the same command as before, and `--stop` and `view` are untouched. ### Current state Observed on a dev VM, with another process listening on the site's port before the start, for three apps (zola, live-server, Vite with `--strictPort`): ``` $ allod site serve http://127.0.0.1:<port> $ echo $? 0 ``` The unit's journal for the same start, live-server's case: ``` ERROR live_server::http_layer::listener] Address 127.0.0.1:<port> is already in use allod-preview-<slug>.service: Failed with result 'exit-code'. ``` Each app failed as its contract requires. `serve` had already returned: `sitePreviewWait` (`cmd/allod/site_serve.go:201`, at `ef380c8`) takes a connection to the port as good news while the unit is up, and the unit is still up while `nix run` is evaluating, before the app has tried to bind. The address printed is the other process's. `docs/allod-site-preview.md:10` describes this case as reported "as serving". ### Default Before starting a unit that is not running (`cmd/allod/site_serve.go:114`), `serve` connects to the port once. An answer means the port is taken: exit 1, a message naming the port and the unit that was not started, and no `systemd-run`. The check comes after the checks of the checkout path and the flake's `preview` app, so a fault in the site is reported before a port that is only busy for now. A unit that is already running is not checked: finding the site's own preview up is the ordinary case and still prints its address. ### What this leaves open Another process can take the port in the seconds between the check and the app's bind, while `nix run` evaluates. `serve` would then print the address with exit 0 while the unit's journal shows the app failing. With a port the owner assigned in the registry, which nothing else is aiming for, this is rare. Closing it means confirming that the listening socket belongs to a process of the unit, which was built and measured under allod/tools#249 and costs about a hundred lines that read kernel files. It is a follow-up only if the case is seen in use. ### Validation - A port held by another process, from the registry and from `--port`: exit 1, the port named, no address printed, no unit started. - A site with a registry port, and one given `--port`, on a free port: started with the same `systemd-run` arguments as before. - A second `serve` while the preview is running: the address, exit 0. - A site with no port: refused as today. ### Scope In: the check before a start in `serve`, its message, its tests, the contract bullet in `docs/allod-site-preview.md`, and the exit-code line of `serve --help`. Out: picking a port for a site that has none, and `view` learning a port from the VM, both dropped with allod/tools#249; which registry a dev VM reads, allod/archetypes#119.
vnprc closed this issue 2026-09-29 02:51:33 +01:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
allod/tools#252
No description provided.