Skip to content

Fix: Publish the heartbeat port only after binding succeeds - #1595

Open
YEthYuan wants to merge 1 commit into
ipython:mainfrom
YEthYuan:codex/heartbeat-bound-port
Open

YEthYuan wants to merge 1 commit into
ipython:mainfrom
YEthYuan:codex/heartbeat-bound-port

Conversation

@YEthYuan

@YEthYuan YEthYuan commented Nov 13, 2026 •

Copy link
Copy Markdown

When another process claims the heartbeat's candidate port before the heartbeat thread binds it, the existing retry logic selects a replacement port. However, IPKernelApp has already copied the original port, so it can write a connection file that points clients at the wrong endpoint.

Wait for heartbeat binding to complete before copying and logging the port. Heartbeat.start() now waits for a future completed after successful binding. The ZeroMQ socket is still created, bound, and used on the heartbeat thread; Heartbeat.addr is updated after successful binding. Socket setup and exception handling retain their existing implementation.

Port conflict before and after this change

P is the initial candidate port; Q is the replacement selected after a bind conflict. The temporary socket releases P before the actual heartbeat socket binds it.

sequenceDiagram
    participant App as Kernel startup
    participant OS as Operating system
    participant Other as Another process
    participant HB as Heartbeat thread

    App->>OS: Bind temporary TCP socket to port 0
    OS-->>App: Assign port P
    App->>OS: Close temporary socket
    Note over App,OS: P is available again
    Other->>OS: Bind socket with automatic port selection
    OS-->>Other: Assign and bind P

    alt Before this change
        App->>App: Copy candidate P into hb_port
        App->>HB: Start heartbeat thread
        HB->>OS: Bind heartbeat socket to P
        OS-->>HB: Address already in use
        HB->>OS: Retry binding on port Q
        OS-->>HB: Binding succeeds
        App->>App: Write connection file with hb_port P
        Note over App,HB: Clients receive P but heartbeat listens on Q
    else With this change
        App->>HB: Start heartbeat thread and wait for binding
        HB->>OS: Bind heartbeat socket to P
        OS-->>HB: Address already in use
        HB->>OS: Retry binding on port Q
        OS-->>HB: Binding succeeds
        HB-->>App: Signal successful binding
        App->>App: Copy bound port Q into hb_port
        App->>App: Write connection file with hb_port Q
        Note over App,HB: Published port matches the bound heartbeat socket
    end
Loading

@YEthYuan YEthYuan changed the title Wait for heartbeat binding before publishing its port Fix: Publish the heartbeat port only after binding succeeds Nov 13, 2026
@YEthYuan
YEthYuan force-pushed the codex/heartbeat-bound-port branch from d6b132b to 6e3abe4 Compare November 13, 2026 08:10
@YEthYuan
YEthYuan force-pushed the codex/heartbeat-bound-port branch from 6e3abe4 to a4a708b Compare November 13, 2026 08:16
@YEthYuan
YEthYuan marked this pull request as ready for review November 13, 2026 08:22

This branch has not been deployed

No deployments
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.

1 participant