Skip to content

LocalWalSyncImpl._flush - Out of Memory crash#4539

Open
aaravgarg wants to merge 1 commit intomainfrom
fix/ios-crash-local-wal-sync-oom
Open

LocalWalSyncImpl._flush - Out of Memory crash#4539
aaravgarg wants to merge 1 commit intomainfrom
fix/ios-crash-local-wal-sync-oom

Conversation

@aaravgarg
Copy link
Collaborator

Summary

  • Fix OOM crash by writing WAL frames incrementally using IOSink instead of building entire data list in memory
  • Fix "Cannot add to unmodifiable list" crash by initializing _wals as mutable [] instead of const []
  • Free in-memory WAL data after flushing to disk to reduce memory pressure
  • Gracefully skip WALs with unavailable file paths instead of throwing

Crash Stats (combined iOS + Android)

  • OOM Events: 21 (iOS)
  • OOM Users affected: 7 (iOS)
  • Unmodifiable list Events: 889 (Android)
  • Unmodifiable list Users affected: 6 (Android)
  • Crashlytics (iOS OOM): View in Console
  • Crashlytics (Android unmodifiable list): View in Console

Test plan

  • Verify WAL flushing still works correctly
  • Test with large WAL data (should not OOM)
  • Verify _wals list operations work (add, remove, etc.)

🤖 Generated with Claude Code

- Change _wals initialization from const [] to mutable [] to prevent
  "Cannot add to unmodifiable list" crash
- Write WAL frames to disk incrementally using IOSink instead of
  building entire data list in memory to prevent OOM
- Free in-memory data after flushing to disk
- Continue instead of throwing when file path is unavailable

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@aaravgarg aaravgarg requested a review from mdmohsin7 February 1, 2026 23:22
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request effectively addresses a critical Out of Memory (OOM) crash during WAL flushing by switching to an incremental write approach using IOSink. The changes also fix a crash related to modifying an unmodifiable list and gracefully handle cases where a WAL file path is unavailable. Additionally, a subtle but critical bug involving loop variable shadowing has been resolved. The memory footprint is further reduced by clearing WAL data after it's been flushed to disk. The overall solution is robust and well-implemented. I've added one suggestion to further optimize the file writing logic for better performance and readability.

Comment on lines +220 to +225
final byteFrame = ByteData(frame.length);
for (int k = 0; k < frame.length; k++) {
byteFrame.setUint8(k, frame[k]);
}
sink.add(Uint32List.fromList([frame.length]).buffer.asUint8List());
sink.add(byteFrame.buffer.asUint8List());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

This block manually copies bytes from frame into a new ByteData buffer. Since wal.data likely contains Uint8List instances from the byte stream, frame (which is a sublist of an element from wal.data) is also a Uint8List. You can add it to the sink directly, which is more efficient and readable, avoiding the unnecessary allocation and byte-by-byte copy.

            sink.add(Uint32List.fromList([frame.length]).buffer.asUint8List());
            sink.add(frame);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant