I'm doing mmap() on a file that can be unmounted ( the file is located on an USB device which the user can remove at any time ), and my application crashes if the file is unmounted and then i try to access any element in the buffer.
Any solutions to this ?
First of all, I would like to say this should serve as a good argument not to use mmap
unnecessarily as an "optimized read" or similar. Aside from device removal, issues like file truncation by other processes can cause accesses to fault with SIGBUS
.
If you do really need to use mmap
, you could install a signal handler for SIGBUS
. Its task should basically be to:
SIGBUS
occurred, so the faulting code can be aware.mmap
with MAP_FIXED
to map a new anonymous page over top of the faulting page. Optionally fill it with data which will be recognized by the code accessing the map as erroneous; this could make step 1 unnecessary.An alternative approach would be to set a global (or thread-local) jmp_buf
before accessing the map, and have the signal handler simply call longjmp
.
Note that neither mmap
nor longjmp
is async-signal-safe, but the SIGBUS
in question is not an asynchronous signal (although it should perhaps be considered one if the faulting access happened inside a non-async-signal-safe library function such as sscanf
). As long as it's your own code, and not library functions, accessing the map, you should be safe with either. And mmap
is async-signal-safe in most/all real-world implementations, so you should be okay with the first solution in practice even if it's not formally correct.
The simplest thing is to set up a signal handler that will check for accesses to memory locations that correspond to mmap
ed addresses.
You would use the sigaction
form of signal handlers, rather than the simpler signal
handlers as sigaction
handlers receive information in the struct __siginfo *
parameter corresponding to the address of the signal. This can be checked to see if it is within the address range of the mmap
ed file.
mmap
is great when you don't want to deal with the complications of buffer reading/writing of data, but you only get one form of error (a signal) due to something going wrong. with the read
/write
mechanism, you can get the errno
and determine what happened. It is very much a developer choice in this case.
To jump to a location after receiving the signal then you will need to make use of the setjmp
and longjmp
/siglongjmp
- see some use of this in this question
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With