fix: resolve DeadObjectException, OOM, and ANR from Sentry#502
fix: resolve DeadObjectException, OOM, and ANR from Sentry#502torlando-tech merged 7 commits intomainfrom
Conversation
Fix three high-impact Sentry issues: - COLUMBA-14: Wrap IInitializationCallback invocations in try-catch for RemoteException to prevent service crash when client dies during async initialization (77 events / 17 users) - COLUMBA-P: Stream file attachment hex encoding to disk instead of allocating CharArray(size*2) in memory, preventing OOM on large files. Uses existing _data_ref pattern. (3 events / 2 users) - COLUMBA-3K/2Z/2R: Add missing withContext(Dispatchers.IO) to announceDestination() to move synchronous AIDL binder call off main thread, preventing ANR (4 events / 3 users) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Greptile SummaryThis PR addresses three high-impact production issues identified in Sentry with targeted, well-scoped fixes: Fix 1: DeadObjectException (COLUMBA-14) - Wrapped all 4 Fix 2: OOM in file attachments (COLUMBA-P) - Introduced Fix 3: ANR in announceDestination (COLUMBA-3K/2Z/2R) - Added Key observations:
Confidence Score: 4/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[User sends message with file attachment] --> B{File size check}
B --> C[buildFieldsJson with cacheDir]
C --> D[buildFileAttachmentsArray]
D --> E{cacheDir != null?}
E -->|Yes| F[Create hex file: outgoing_timestamp_index.hex]
F --> G[streamHexToFile - O1 memory]
G --> H[Store _data_ref path in JSON]
E -->|No| I[Fallback to toHexString - in-memory]
I --> H
H --> J[ConversationRepository.extractFileAttachmentsForSent]
J --> K{Has _data_ref?}
K -->|Yes, data empty| L[Pass through existing _data_ref]
K -->|No, has data| M[Extract to disk via saveAttachment]
L --> N[Message ready for transmission]
M --> N
style F fill:#e1f5e1
style G fill:#e1f5e1
style L fill:#e1f5e1
Last reviewed commit: 22a0fc4 |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
The PR added applicationContext: Context as the first constructor parameter but the test files weren't updated, causing compilation failures in all 4 CI test shards. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
streamHexToFile performs blocking file I/O which should not run on Dispatchers.Default (CPU-bound pool sized to core count). Dispatchers.IO shares threads with Default for the CPU work but can expand beyond the core count when threads block on write syscalls. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
data/src/main/java/com/lxmf/messenger/data/repository/ConversationRepository.kt
Show resolved
Hide resolved
app/src/main/java/com/lxmf/messenger/viewmodel/MessagingViewModel.kt
Outdated
Show resolved
Hide resolved
Hex files from streamHexToFile were written directly to cacheDir root, so cleanupAllTempFiles never removed them. Move to outgoing_hex/ subdirectory and add it to the cleanup list. Also stub applicationContext.cacheDir in tests to return a real temp directory so streamHexToFile can write during send tests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Cancel serverScope before calling server.stop() to prevent queued coroutines from re-acquiring isRunning after stop clears it. Add withTimeout safety net to prevent CI hangs if teardown blocks. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
If streamHexToFile throws (disk full, permission error) during buildFieldsJson, the exception previously propagated past saveMessageToDatabase — the message was delivered to the recipient but disappeared from the sender's conversation history. Wrap buildFieldsJson in try-catch(IOException) and fall back to text-only fields so the message is always saved locally. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Images using the ORIGINAL preset can be up to 25MB, which would allocate a 50MB CharArray in toHexString(). Use streamHexToFile() with _file_ref for images above 512KB, matching the file attachment pattern. The read side already handles _file_ref for field 6. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
Fixes three high-impact Sentry issues from the last 7 days (84 events / 22 users total):
COLUMBA-14 (77 events / 17 users):
DeadObjectExceptioncrashes the service process when a client dies during async initialization. Wraps all 4IInitializationCallbackinvocations intry-catch(RemoteException), matching the existingCallbackBroadcasterpattern.COLUMBA-P (3 events / 2 users): OOM in
toHexString()when sending large file attachments. A 111MB file creates a 222MBCharArrayon top of the sourceByteArray. Replaced with streaming hex-to-disk via a newByteArray.streamHexToFile()extension that uses O(1) memory. Uses the existing_data_reffile-path pattern already supported by the read side (MessageMapper.loadFileAttachmentData()).COLUMBA-3K/2Z/2R (4 events / 3 users): ANR in
announceDestination()— missingwithContext(Dispatchers.IO)caused the synchronous AIDL binder call (which blocks on Python's GIL) to run on the main thread. All 15+ other binder methods in the file already useDispatchers.IO; this one was missed.Changes
ReticulumServiceBinder.kttry-catch(RemoteException)FileUtils.ktByteArray.streamHexToFile()extensionMessagingViewModel.kt@ApplicationContext, stream file hex to disk via_data_ref, extractbuildFileAttachmentsArray()andbuildAppExtensions()frombuildFieldsJson()ConversationRepository.kt_data_refinextractFileAttachmentsForSent()ServiceReticulumProtocol.ktwithContext(Dispatchers.IO)toannounceDestination()Manual test plan
Fix 1: DeadObjectException (COLUMBA-14)
Client died before initializationwarning (not a crash)Fix 2: OOM in file attachments (COLUMBA-P)
.hextemp file was created in the cache directory (adb shell ls /data/data/com.lxmf.messenger/cache/outgoing_*.hex)_data_ref).hexfiles are cleaned up by the existingcleanupAllTempFiles()routineFix 3: ANR in announceDestination (COLUMBA-3K/2Z/2R)
ANRorInput dispatching timed out— should see noneRegression checks
_data_refin fieldsJson🤖 Generated with Claude Code