fix: no pharn-owned project file can hang a command or be read without bound - #225
Merged
Merged
Conversation
…t bound
pharn.config.json, pharn.records.json and .pharn.lock were read with a
plain readFileSync. A FIFO at any of them blocked in open(2) forever — for
`update` and a re-run `init` while holding the project lock, so every other
pharn command in the project was refused too — and a symlink to /dev/zero
was read until memory ran out.
- New lib/bounded-read.ts (readBoundedFile): one descriptor opened
O_NONBLOCK, fstat-checked as a regular file of at most 16 MiB, read from
that same descriptor; never throws. Fixed reasons ("is not a regular
file", "is larger than 16 MiB", "could not be read (<errno>)").
- readRecords, readPharnConfig, configFingerprint, init's two tolerant
config reads and the lock's readRawAt read through it. Each keeps its
existing unreadable outcome: records -> a named `invalid`, config ->
null / `unreadable:<code>`, lock -> presumed live, then broken.
- FIFO cases for records, config and a young/old lock run in a child with
a hard timeout (they hung on the base).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0199owRmYfskqYQVQrVP679o
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this changes
pharn.config.json,pharn.records.jsonand.pharn.lockwere read with a plainreadFileSync. That caused two problems:open(2)forever. Forpharn update, and for a re-runpharn init, that happened while holding the project lock, so every otherpharncommand in the project was refused too./dev/zerowas read until memory ran out.A new
src/lib/bounded-read.ts(readBoundedFile) reads through one descriptor opened withO_NONBLOCK. It checks withfstatthat the file is a regular file of at most 16 MiB, reads from that same descriptor, and never throws. It is the same approachhook-wiring.tsanddetect-archetype.tsalready use.These six readers now go through it:
readRecords,readPharnConfig,configFingerprint, init's two tolerant config reads, and the lock'sreadRawAt. Each keeps its existing "unreadable" outcome:pharn.records.jsoninvalidpharn.config.jsonnull/unreadable:<code>.pharn.lockType of change
feat— new stack option, wizard step, or command capabilityfix— bug fixdocs— docs-only changechore/refactor— tooling or internal restructure, no behavior changeArea(s) touched
lib/bounded-read (new) | lib/install-records | lib/pharn-config | lib/project-lock | steps/overwrite-check | steps/install-archetype | docs
Checklist
.js-extension import convention.tests/*.test.ts. I ran the FIFO cases for records, config, and a young and an old lock against the unchanged code first: each hung inopen(2)until its 15 s child timeout killed it.docs/page (docs/reference/pharn-records.md,docs/troubleshooting.md).Quality gates
npm run checkpasses locally (1664 tests). I ran it as root with the DAC-override capabilities dropped (CI-equivalent).npm run buildsucceeds.npm run test:coveragepasses.Notes for the reviewer
unreadable:EISDIR. On Windows, where opening a directory throws, the reason is normalized so both platforms say "is not a regular file".pharn.config.jsonstill gets the existing "No pharn.config.json found. Runpharn initfirst." answer. That was already the wording for a directory or a permissions problem; making it more precise would change every command's documented contract, so it's left for its own change.🤖 Generated with Claude Code
https://claude.ai/code/session_0199owRmYfskqYQVQrVP679o
Generated by Claude Code