#2437

bug(windows): bound hallway sidecar temporary-file allocation

Openfatkobraopened 1mo ago

Summary

hallways._save_hallways() publishes the palace-scoped hallways.json through an adjacent tempfile.mkstemp() file followed by os.replace().

PR #2420 demonstrated that, on affected Python/Windows behavior, repeated PermissionError results during temporary-name allocation can be interpreted as candidate collisions and cause an extremely large retry loop before eventually surfacing an unrelated-looking EEXIST.

The hallway writer retains the same unbounded standard-library allocation shape.

Current path

_save_hallways() currently:

  1. creates the destination directory
  2. calls tempfile.mkstemp() beside hallways.json
  3. writes the complete payload
  4. applies restrictive permissions
  5. publishes it with os.replace()

Temporary-file allocation occurs before the existing cleanup try block.

Impact

When the destination directory refuses every adjacent temporary name, hallway persistence can hang for an impractical amount of time or fail only after exhausting the standard-library retry budget.

This can affect hallway recomputation and hallway deletion.

The previous hallways.json remains valuable state and must not be truncated merely because an adjacent temporary file cannot be created.

Desired behavior

  • place a deterministic upper bound on temporary-name allocation
  • retain exclusive creation and cryptographically strong random names
  • preserve the atomic os.replace() publication model
  • preserve restrictive file permissions
  • propagate a prompt, actionable filesystem error when the directory cannot accept a temporary file
  • do not fall back to truncating the existing hallways.json in place
  • do not leave a temporary file behind after write, chmod, or replace failures
  • avoid copying a config-private helper into this module; use a shared internal atomic-file utility where practical

Regression coverage

Add tests proving that:

  • repeated EPERM or EACCES reaches the caller after a bounded number of opens
  • the previous hallways.json remains byte-for-byte unchanged
  • no temporary file remains after failure
  • a genuine first-name collision is retried successfully
  • a successful save still publishes complete JSON atomically
  • restrictive permissions remain applied where supported

Relationship

Follow-up to #2420 and the review observation identifying the remaining hallways.py allocation path.

This is intentionally separate from #2392 because config persistence has an explicit in-place fallback, while hallway persistence should preserve the existing sidecar rather than abandon atomic publication.

Activity

0

No activity yet.