Skip to content

fix: prevent SIGBUS crash when reading images from external volumes#1387

Open
olegsatov wants to merge 1 commit into
CyberTimon:mainfrom
olegsatov:fix-mmap-sigbus
Open

fix: prevent SIGBUS crash when reading images from external volumes#1387
olegsatov wants to merge 1 commit into
CyberTimon:mainfrom
olegsatov:fix-mmap-sigbus

Conversation

@olegsatov

Copy link
Copy Markdown

Summary

RapidRAW crashes with SIGBUS (EXC_BAD_ACCESS / KERN_MEMORY_ERROR) when an image file is memory-mapped and the kernel later fails to page it in — e.g. an external/USB drive disconnects or returns an I/O error, a network share drops, or the file is truncated/replaced by another process after mapping.

Crash report (macOS 26.4, ARM64), faulting thread:

_platform_memmove
rawler::rawsource::RawSource::new_from_slice
rapidraw_lib::raw_processing::develop_raw_image
rapidraw_lib::image_loader::load_base_image_from_bytes

Kernel triage: VM - Page has error bit set, and the faulting address lies inside a valid mapped file region — i.e. not a bad pointer, but a failed page-in from the backing file. In my case two worker threads faulted simultaneously on two different mapped files when the external drive the library lives on glitched.

Since this is a signal, not a panic, catch_unwind can't contain it and the whole app dies. The existing "fall back to fs::read" branches only trigger when creating the mapping fails — they can't help once a page-in fails later.

Fix

Replace read_file_mapped with read_file_bytes — a plain fs::read with the same pre-checks — at all call sites (image load, thumbnails, EXIF batch read, preview, export, negative conversion). I/O errors now surface as regular Err results that the UI already handles, instead of killing the process.

No performance regression is expected: every consumer (rawler::RawSource::new_from_slice, image decoders) immediately copies the entire buffer into an owned allocation anyway, so mmap never saved a copy here — it only added the SIGBUS risk.

Also removes the now-unused memmap2 dependency and the ReadFileError::Locked variant (the advisory try_lock_shared never meaningfully protected these reads).

Testing

  • cargo check clean, no new warnings (on top of current main).
  • I could not artificially reproduce the original crash — it requires a storage-level fault (drive disconnect / I/O error) mid-load. After this change the failure mode is a normal read error returned to the UI instead of a process crash.

@olegsatov
olegsatov requested a review from CyberTimon as a code owner July 16, 2026 21:11
@CyberTimon

Copy link
Copy Markdown
Owner

What do you think about performance? Will this have a huge effect on NAS drives?

For context see #347

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.

2 participants