Skip to content

fix(daemon): hash a verified peer image copy once, not on every HELLO (#1955) - #2335

Merged
DeusData merged 1 commit into
mainfrom
fix/issue-1955
Sep 30, 2026
Merged

DeusData merged 1 commit into
mainfrom
fix/issue-1955

Conversation

@DeusData

Copy link
Copy Markdown
Owner

A client whose binary is a different file with identical bytes (a second
install path, a package-manager copy) misses the daemon's metadata-only
active-image check, so the HELLO proves the build by SHA-256 over the peer's
whole image. The release binary is ~300 MB: that hash takes ~1.2 s on an
M5 Pro with a warm cache and longer under indexing load or on slower x64,
while the client grants connect+HELLO only 1000 ms. The client abandoned the
HELLO, re-probed, and every re-probe started the same hash again on a fresh
worker, so such a client waited out the whole 30 s startup deadline against a
healthy daemon that kept serving its existing sessions.

The daemon now retains the reference of each peer image whose full
fingerprint matched its own build (bounded to 8 distinct files) and admits
later peers mapping that same unchanged file by metadata, exactly like the
active image. The retained reference pins the inode, so its stat identity
cannot be reused by another file. The accepted set of images is unchanged:
mismatched and unverifiable peers take the same paths as before.

Before, same daemon, identical copy B of the running binary A:
B cli --json index_status -> 34.9 s, "answered no rendezvous within 30000 ms"
After:
B first call 4.9 s (one hash), then 1.4 s, 1.4 s (same as A)

Fixes #1955

…#1955)

A client whose binary is a different file with identical bytes (a second
install path, a package-manager copy) misses the daemon's metadata-only
active-image check, so the HELLO proves the build by SHA-256 over the peer's
whole image. The release binary is ~300 MB: that hash takes ~1.2 s on an
M5 Pro with a warm cache and longer under indexing load or on slower x64,
while the client grants connect+HELLO only 1000 ms. The client abandoned the
HELLO, re-probed, and every re-probe started the same hash again on a fresh
worker, so such a client waited out the whole 30 s startup deadline against a
healthy daemon that kept serving its existing sessions.

The daemon now retains the reference of each peer image whose full
fingerprint matched its own build (bounded to 8 distinct files) and admits
later peers mapping that same unchanged file by metadata, exactly like the
active image. The retained reference pins the inode, so its stat identity
cannot be reused by another file. The accepted set of images is unchanged:
mismatched and unverifiable peers take the same paths as before.

Before, same daemon, identical copy B of the running binary A:
  B cli --json index_status -> 34.9 s, "answered no rendezvous within 30000 ms"
After:
  B first call 4.9 s (one hash), then 1.4 s, 1.4 s (same as A)

Signed-off-by: Martin Vogel <[email protected]>
@DeusData
DeusData merged commit 30a410b into main Sep 30, 2026
41 checks passed
DeusData added a commit to bmcnaboe/codebase-memory-mcp that referenced this pull request Nov 10, 2026
The fingerprint cache sat in every fingerprinting acquire, including
peer verification. Limit it to the process's own image: every acquire
site now passes the process id to the shared resolve step, which marks
a peer's key invalid, so a peer is never looked up, never committed,
and is hashed on every fingerprint. Re-hashing of verified peer copies
is handled by the runtime service's retained peer references (DeusData#2335).
The daemon's saving is unchanged: it hashes its own image once at start
instead of twice.

A process has one own image, so the cache drops from 8 entries to 1,
which removes the slot search and the round-robin eviction.

The cache comment no longer claims that SetFileTime cannot reset the
Windows change time; SetFileInformationByHandle can set it. Limited to
the own image, the key does not rely on it: Windows keeps a running
image locked against modification for as long as the process, and so
the cache, exists.

Test: daemon_runtime_process_fingerprint_caches_only_own_image spawns
this runner as a peer, whose image has the same file identity as the
own image, and asserts that two peer fingerprints cost two hashes, two
own fingerprints one more, and a later peer fingerprint one more again.
Before this change the second peer fingerprint was served from the
cache.

Signed-off-by: Martin Vogel <[email protected]>
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.

Linux 0.10.5: new MCP/CLI clients intermittently wait 15–30s or time out while healthy daemon serves existing clients

1 participant