# fix\(server\): harden the data-directory lock against concurrent-starter races · pingdotgg/t3code

[View on GitCafe](https://git.cafe/pingdotgg/t3code/commit/eed1a3258fa52fd8629c60b0a532c1fe86b28c06)

Repository: [pingdotgg/t3code](https://git.cafe/pingdotgg/t3code)

Visibility: public

Requested revision: eed1a3258fa52fd8629c60b0a532c1fe86b28c06

Requested commit: eed1a3258fa52fd8629c60b0a532c1fe86b28c06

Commit: eed1a3258fa52fd8629c60b0a532c1fe86b28c06

Tree: 46421ae27e8e2259124487c398fa99d190d1ca27

Author: NoahLinckeScout

Committer: NoahLinckeScout

## Message

```
fix(server): harden the data-directory lock against concurrent-starter races

Review on #8442 found the guard itself re-introduced the corruption it exists
to prevent, plus one rollout gap. All were right.

- A pre-lock server writes no server.lock, only server-runtime.json with its
  live pid, so the file was blind to the running 0.0.34 the upgrade swaps out.
  Read that as a held lock and refuse the same way before anything binds, or
  the auto-update incident still happens once on upgrade day.

- Between one starter reading a stale lock and recreating it, the
  unconditional unlink removed the successor's fresh claim: two starters after
  a crash each unlinked the other's lock and both proceeded. Reclaim now
  refreshes the dead file's mtime across several observation rounds and only
  removes what stays untouched, and the live holder's own heartbeat refreshes
  inside one round, so a live claim can never be reclaimed from under it.

- recordServerLockPort rewrote the lock in place, truncating first; a reader
  in that window decoded an empty holder and reclaimed a live lock. The update
  now goes through write-temp-then-rename, and release never removes a lock it
  cannot decode.

- Lock-create errors stopped being coerced into "taken": a permission or
  disk failure used to surface as "another server is running". Only
  AlreadyExists reads as contention now, and the exhaustion error keeps the
  observation count instead of fixed prose.

Verified: apps/server suite 246 files passed / 2 skipped, 2829 tests passed /
10 skipped (parent: 245 files, 2815 passed). Typecheck exit 0. The new tests
also pin the pre-fix behaviour as failing, not just the new behaviour as
passing.

```

## Parents

- [53dd74b2067df1733d1af3dcb3f4c050423f39e7](https://git.cafe/pingdotgg/t3code/commit/53dd74b2067df1733d1af3dcb3f4c050423f39e7?format=markdown)

[Source at this commit](https://git.cafe/pingdotgg/t3code/tree/eed1a3258fa52fd8629c60b0a532c1fe86b28c06?format=markdown)
