fix(daemon): only announce the pid-publish degrade once it actually published

The warning sat above the degraded exclusive write, but that write can itself
throw EEXIST: a daemon losing an ownership race on a hard-link-incapable volume
announced 'torn-write protection is off for this record' for a record it never
wrote. Announce after the write lands, so the claim is true when it is made.

Also pin describeErrnoCode's no-code branch, which existed for exactly the
exotic-volume error the degrade handles and was never exercised.
This commit is contained in:
Brennan Benson
2026-08-28 08:02:58 -07:00
parent 8b69e9e833
commit 4f6930f569
2 changed files with 26 additions and 1 deletions
@@ -170,6 +170,28 @@ describe('publishDaemonPidFile atomicity', () => {
expect(entries).toEqual([])
})
it('stays silent when the degraded write itself loses the ownership race', () => {
// Same catch arm as the degrade, but nothing was published: announcing lost
// torn-write protection for a record that was never written is a false alarm.
const entries: string[] = []
publishDaemonPidFile(pidPath, { pid: 1, startedAtMs: 5, launchNonce: 'other' })
fsFaults.linkError = Object.assign(new Error('injected ENOTSUP'), { code: 'ENOTSUP' })
expect(() =>
publishDaemonPidFile(pidPath, RECORD, { log: (event) => entries.push(event) })
).toThrow(/EEXIST/)
expect(warnSpy).not.toHaveBeenCalled()
expect(entries).toEqual([])
})
it('names the errno even when the link error carries none', () => {
fsFaults.linkError = new Error('injected link failure with no code')
publishDaemonPidFile(pidPath, RECORD)
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('no errno'))
})
it('keeps exclusive-create semantics on the degraded path too', () => {
publishDaemonPidFile(pidPath, { pid: 1, startedAtMs: 5, launchNonce: 'other' })
fsFaults.linkError = Object.assign(new Error('injected ENOTSUP'), { code: 'ENOTSUP' })
+4 -1
View File
@@ -204,6 +204,10 @@ export function publishDaemonPidFile(
// instead of trading a torn-write window for no pid record at all. Warn because the
// degrade is otherwise invisible: an operator on such a volume (network mount,
// container overlay) should be able to tell the atomic path is not in use.
writeFileSync(pidPath, serializeDaemonPidFile(pidFile), { mode: 0o600, flag: 'wx' })
// Announced only once the degraded write has actually landed: this same arm is
// reached by a lost ownership race, where the write throws EEXIST and nothing
// was published — claiming torn-write exposure for that would be a lie.
// Both channels, matching daemon-endpoint-lifecycle.ts: inside the detached
// daemon stdio is 'ignore' and its startup stderr pipe is destroyed once it is
// up, so console alone reaches nobody on the path this warning exists for.
@@ -212,7 +216,6 @@ export function publishDaemonPidFile(
`[daemon] pid-record hard-link publish failed (${describeErrnoCode(error)}); ` +
'degrading to the non-atomic exclusive write — torn-write protection is off for this record'
)
writeFileSync(pidPath, serializeDaemonPidFile(pidFile), { mode: 0o600, flag: 'wx' })
}
} finally {
try {