fix(bitdefender): atomic cache writes + advisory lock on write-through (M3)

Audit fix M3: _write_cache did a non-atomic CACHE_FILE.write_text and the
write-through helpers did unlocked read-modify-write, so a crash mid-write could
truncate inventory.json and two concurrent gz.py runs could lose an update.
- _write_cache now writes a temp file (fsync) then os.replace() - atomic on the
  same filesystem; a reader/crash can never see a partial file, and a failed
  write leaves the prior cache intact and no .tmp residue.
- Added a best-effort cross-platform advisory lock (_cache_lock) around the
  read-modify-write in _cache_add_group/_cache_add_package; steals a stale lock,
  proceeds unlocked on timeout (a lost update is tolerable, a hang is not).
- Dropped the dead cache.setdefault('companies', ...) line in _cache_add_group.
- Verified: compile clean; unit tests for round-trip, lock acquire/release/steal,
  write-through, temp cleanup on failure, and prior-cache survival.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-25 12:54:50 -07:00
parent d4fd71baab
commit 4d7508382d

View File

@@ -1317,4 +1317,9 @@ def main() -> int:
"httpx" if _HAS_HTTPX else "urllib")
return 0
except GravityZoneError as exc:
prin
print(f"[ERROR] {exc}", file=sys.stderr)
return 1
if __name__ == "__main__":
raise SystemExit(main())