MemoryMappedAudioFormatReader with removable media


#1

I believe this issue should be a problem for any MemoryMapped file (not only audio) but audio is a tricky case if you want to avoid locks and stuttering :slight_smile:

I’ve tried MemoryMappedAudioFormatReader and it works quite well for my needs.
However one stability test I do is:

  • Map a file from removable media (hard-drive connected with USB).
  • I map a WAVE file from ExFAT parition.
  • Play audio and during playback remove the drive physically.
    (pulling the cable, yep… nasty but so is coffee spilled on keyboard and it still happens… - yet to me though… )

I saw this under Win/macOS (macOS Sierra was the most reproducible so far).

juce::MemoryMappedWavReader::getSample(long long, float*) const + 351 (juce_WavAudioFormat.cpp:1514)
with juce_ByteOrder pulling some invalid address.

one more thing, we’ve made a watchers for media using atomic file-state but I guess since this is async it does fail in some cases.

I’ve tested Pro Tools 12.7.1 and it got stuck on some lock,
Ableton survived well (but failed to relink once media was available again).
Traktion (mmm… Waveform) crashed and I guess it’s using the exact code.

And ideas?

Thanks!


#2

Hmmm I don’t think there is anything you can do about this other than using a non memory-mapped solution. See this from the Wikipedia page of “Memory-mapped file”:

I/O errors on the underlying file (e.g. its removable drive is unplugged or optical media is ejected, disk full when writing, etc.) while accessing its mapped memory are reported to the application as the SIGSEGV/SIGBUS signals on POSIX, and the EXECUTE_IN_PAGE_ERROR structured exception on Windows. All code accessing mapped memory must be prepared to handle these errors, which don’t normally occur when accessing memory.

Have you tried using the BufferingAudioReader?


#3

All code accessing mapped memory must be prepared to handle these errors

Doesn’t this just mean that the MemoryMappedAudioFormatReader should be prepared to handle these errors?


#4

Well not really. A sigsegv/sigbus signal is the same signal that is sent on an invalid memory access - so a hard crash (in fact, that’s the crash that you are seeing). JUCE would need to add some way to recover from a hard crash but this is normally done with some kind of crash handler app by the application developer. I don’t think this is something that should be in JUCE.


#5

Thanks. we’'ll look into:

Seems like mmap simplifies one problem but makes a whole new territory of possible problems :wink: