Skip to content

fix: prevent deadlock when sending photo from camera to new contact (…#14679

Closed
benny10ben wants to merge 1 commit intosignalapp:mainfrom
benny10ben:fix/14674-camera-deadlock
Closed

fix: prevent deadlock when sending photo from camera to new contact (…#14679
benny10ben wants to merge 1 commit intosignalapp:mainfrom
benny10ben:fix/14674-camera-deadlock

Conversation

@benny10ben
Copy link
Copy Markdown
Contributor

Fixes #14674

First time contributor checklist

Contributor checklist

  • I am following the Code Style Guidelines
  • I have tested my contribution on these devices:
    • Samsung Galaxy S23, Android 16
    • Android Emulator Pixel 9, Android 16
  • My contribution is fully baked and ready to be merged as is
  • I ensure that all the open issues my contribution fixes are mentioned in the commit message of my first commit using the Fixes #1234 syntax

Description

Problem

When opening the in-app camera from the chat list (not from inside a conversation),
taking a photo, and sending it to a contact, a permanent deadlock occurs. A spinning
indicator appears over the image and never resolves. Backing out and relaunching the
app leaves it in a broken state where messages cannot be sent until the app is
force-stopped or the device is rebooted.

Reported log line:

W DeadlockDetector: Found a long block! Blocked for at least 5000 ms.

Root cause

When the camera is launched from the chat list, destination is set to
ChooseAfterMediaSelection — meaning no recipient is known yet. However,
shouldPreUpload() only checked network metering, so on a Wi-Fi connection
isPreUploadEnabled was set to true even with a null recipient.

This caused startUpload(media, null) to fire immediately after the photo was
taken, spawning a background thread (Thread A) that inserted attachment rows into
SQLite and held a write lock.

When the user later picked a contact and hit send, repository.send() called
uploadRepository.applyMediaUpdates(null) on a second thread (Thread B), which
needed the same write lock. Thread B blocked waiting on Thread A, Thread A stalled
waiting on Thread B's downstream work, and neither thread ever completed.

Fix

Added a single guard to shouldPreUpload() in MediaSelectionViewModel:

// Before
private fun shouldPreUpload(metered: Boolean): Boolean {
    return !metered
}
 
// After
private fun shouldPreUpload(metered: Boolean): Boolean {
    return !metered && !isContactSelectionRequired
}

isContactSelectionRequired is already computed from destination at init time and
exactly captures the "recipient not yet known" state. Setting isPreUploadEnabled
to false in this case prevents the upload thread from spawning at all, eliminating
the lock contention entirely.

All other entry points (inside-chat camera, gallery, editor, share, stories) pass a
concrete destination with a known recipient, so isContactSelectionRequired is
false for all of them — their behaviour is completely unchanged.

Testing

Reproduced the deadlock on Samsung Galaxy S23 / Android 16 following the exact steps
in issue #14674. Confirmed the fix resolves it. Also verified on Android Emulator
Pixel 9 / Android 16 that the inside-chat camera flow, gallery send, and share flow
all continue to work correctly with pre-upload enabled as before.

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.

Sending photo from in-app camera causes deadlock

1 participant