Skip to content

A client reaches only a server it may use; an orphaned server exits (0.6.2) - #32

Merged
trissim merged 5 commits into
mainfrom
fix/B7-server-isolation
Oct 12, 2026
Merged

trissim merged 5 commits into
mainfrom
fix/B7-server-isolation

Conversation

@trissim

@trissim trissim commented Oct 12, 2026

Copy link
Copy Markdown
Contributor

OpenHCS surface B7. A client attached to whatever answered at an address, and nothing stopped a server whose starter was gone.

What changes

  • A server holds an EndpointLaunch (code root, the process that started it, audience) and reports it in every heartbeat (PongResponse.launch).
  • EndpointAudience is a registered family: OwnerOnlyAudience (a non-persistent server) and AnySessionAudience (a persistent one). The wire carries the registry name.
  • ZMQClient.launch() is what a client hands the server it starts. After the start, the client connects only if the ready server reports exactly that launch. On a mismatch it stops its own child and leaves the other server's socket files alone.
  • On attach (connect at an occupied address, connect_existing), a local server must report a launch, its code root must equal the client's, and its audience must admit the client process. Otherwise the client raises EndpointLaunchMismatchError, which names the address and the reason. A remote host is not compared: its paths and process ids mean nothing on this machine.
  • ZMQServer.process_messages checks its owner once a second. When the owner is gone, an owner-only server cancels its work and stops; an any-session server stops once it has no running or queued execution.
  • ZMQConfig.socket_root() owns where socket and lock files live (~/.<app_name> by default; both transports read it). An application overrides it to keep installations apart.
  • TransportDeclaration.private_endpoint(config) gives a caller an address of its own: a new socket directory for IPC, the first unbound pair for TCP.
  • code_root() on clients and servers defaults to the directory the class's top-level package is imported from. An application with a declared import root overrides it on both.

Callers must change

  • A _spawn_server_process implementation must pass self.launch() to the server it starts (EndpointLaunch.to_argument / from_argument for a command line), or the client refuses the server.
  • A third-party TransportDeclaration must implement private_endpoint.

Nothing public is removed, so this is 0.6.2. Not tagged or released here.

Not changed: connect still kills the listener of an unresponsive TCP address before starting its own server (_kill_processes_on_port). That process may belong to someone else.

Tests

tests/test_endpoint_launch.py (10 tests, real server processes): two servers from two code roots and a client refused at the other's address; an owner-only server refuses another process and a persistent one admits it; a server that reports no launch is refused; a server exits after its owner is killed (both audiences); a persistent orphan finishes its work first.

Local run: 383 passed, 2 skipped, 2 failed. The 2 failures are test_ack_return_route IPC cases whose socket path under my long --basetemp exceeds sun_path; both pass with a short one.

🤖 Generated with Claude Code

trissim and others added 2 commits October 11, 2026 20:20
…0.6.2

A server reports its launch (code root, starting process, audience) in every
heartbeat. A client connects to a server it started only if that server
reports the launch it was handed, and attaches to another only if the code
root matches and the audience admits the client process. A server whose
starting process is gone stops: owner-only at once, any-session once idle.
ZMQConfig.socket_root owns where socket and lock files live, and
TransportDeclaration.private_endpoint gives a caller an address of its own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 12, 2026 00:51

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@trissim
trissim merged commit beea6b5 into main Oct 12, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants