mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
2.6 KiB
2.6 KiB
Weekly Race Condition Report: 2026-02-14
Audit Overview
- Agent: bitvid-race-condition-agent
- Focus Areas:
js/nostr/client.js,js/nostr/managers/ConnectionManager.js,js/nostr/videoEventBuffer.js - Cadence: Weekly
Executive Summary
One critical race condition was identified in the NostrClient initialization logic. The client flagged itself as isInitialized = true synchronously at the start of the init() method, before the connection pool was actually ready. This allowed concurrent calls (or UI components checking the flag) to access the uninitialized pool, causing crashes (TypeError: Cannot read properties of null).
Findings
1. Critical: NostrClient Initialization Race
-
Location:
js/nostr/client.js -
Severity: Critical
-
Description: The
init()method setthis.isInitialized = trueimmediately to prevent re-entrant calls. However,ensurePool()andconnectToRelays()are asynchronous. Any component checkingclient.isInitializedduring this window would proceed to use the client and crash. -
Interleaving:
- Caller A calls
client.init(). client.isInitializedbecomestrue.- Caller A awaits
restoreLocalData()(async). - Caller B checks
client.isInitialized->true. - Caller B calls
client.subscribeVideos(). subscribeVideoscallsthis.pool.sub.this.poolisnull(because Caller A hasn't reachedensurePoolyet).- Crash.
- Caller A calls
-
Fix Implemented:
- Introduced
this.initPromiseto track the ongoing initialization. init()now returns the existing promise if called concurrently.this.isInitializedis only set totrueafter the pool is ready and relays are connected.- Fix validated with a new reproduction test
tests/race/nostr-client-init-race.test.mjs.
- Introduced
Other Observations
VideoEventBuffer (Low Risk)
js/nostr/videoEventBuffer.jsuses a debounce timer (scheduleFlush) and checksdocument.hiddento prevent UI thrashing.- A potential "render race" exists where
flush()triggersonVideobefore NIP-71 metadata is fully hydrated. This is an intended trade-off for responsiveness (Stale-While-Revalidate pattern) and not a data corruption bug.
ConnectionManager (Safe)
js/nostr/managers/ConnectionManager.jsproperly guardsensurePoolwiththis.poolPromise, which prevented double-instantiation but didn't protect theNostrClientwrapper from the race described above.
Next Steps
- Next Audit: Review
js/nostr/nip07Permissions.jsandjs/nostr/nip46Client.jsfor signer negotiation races. - Monitoring: Watch for
Cannot read properties of nullerrors in Sentry related topool.sub.