2012-10-15 7 views
5

Sto facendo mmap() su un file che può essere smontato (il file si trova su un dispositivo USB che l'utente può rimuovere in qualsiasi momento), e la mia applicazione si blocca se il file è smontato e quindi provo ad accedere a qualsiasi elemento nel buffer.Evita il crash dopo aver fatto mmap() su un file smontato

Qualche soluzione a questo?

risposta

-1

Non accedere a un file non disponibile. Controlla se il file è ancora presente o utilizza un file che non può essere smontato.

+4

Non penso che sia molto utile a causa delle possibili condizioni di gara. Sarebbe utile aspettarsi e prendere 'SIGBUS' attorno al codice che accede alla regione mappata? O qualcosa di simile? –

+1

No. 'SIGBUS' non è necessariamente recuperabile, sebbene alcune implementazioni ritentino l'istruzione di errore dopo il ritorno dal gestore. –

+0

@SimonRichter Non è necessario riprovare l'istruzione di errore, è solo necessario determinare che non è possibile procedere con una lettura/scrittura, dopo di che si interrompe il tentativo di accedere alla regione e tornare al chiamante con qualche indicazione di errore. Forse 'setjmp()'/'longjmp()' sarebbe in grado di evitare la riesecuzione dell'istruzione di errore. –

2

La cosa più semplice è impostare un gestore di segnale che verificherà l'accesso alle posizioni di memoria che corrispondono agli indirizzi mmap ed.

si può usare il sigaction forma di gestori di segnale, piuttosto che i più semplici signal gestori come sigaction gestori ricevono le informazioni nel parametro struct __siginfo * corrispondente all'indirizzo del segnale. Questo può essere controllato per vedere se si trova all'interno del range di indirizzi del file editore mmap.

mmap è ottimo quando non si vuole affrontare le complicazioni della lettura/scrittura dei dati del buffer, ma si ottiene solo una forma di errore (un segnale) a causa di qualcosa che non va. con il meccanismo read/write, è possibile ottenere il errno e determinare cosa è successo. In questo caso è una scelta molto sviluppatore.

per passare a una posizione dopo aver ricevuto il segnale allora si avrà bisogno di fare uso della setjmp e longjmp/siglongjmp - vedere un certo uso di questo this question

6

Prima di tutto, vorrei dire che questo dovrebbe servire come argomento valido per non utilizzaremmap inutilmente come "lettura ottimizzata" o simile. A parte la rimozione del dispositivo, problemi come il troncamento dei file da parte di altri processi possono causare l'accesso agli errori con SIGBUS.

Se è davvero necessario utilizzare mmap, è possibile installare un gestore di segnale per SIGBUS. Il suo compito dovrebbe essere sostanzialmente a:

  1. impostare una (se il programma è multi-threaded o thread-local,) flag globale che un SIGBUS si è verificato, in modo che il codice ha provocato l'errore può essere a conoscenza.
  2. Chiama il mmap con MAP_FIXED per mappare una nuova pagina anonima sopra alla pagina di errore. Opzionalmente riempirlo con dati che saranno riconosciuti dal codice che accede alla mappa come errati; questo potrebbe rendere superfluo il passaggio 1.

Un approccio alternativo potrebbe essere quello di impostare un globale (o thread-locale) jmp_buf prima di accedere la mappa, e hanno il gestore di segnale semplicemente chiamare longjmp.

Nota che né mmaplongjmp è async-signal-safe, ma la SIGBUS in questione non è un segnale asincrono (anche se dovrebbe forse essere considerato uno se l'accesso ha provocato l'errore è accaduto all'interno di una libreria non async-signal-safe funzione come sscanf). Fintanto che è il tuo codice personale, e non le funzioni di libreria, ad accedere alla mappa, dovresti essere al sicuro con entrambi. E mmap è sicuro per il segnale asincrono nella maggior parte/tutte le implementazioni del mondo reale, quindi dovresti essere in regola con la prima soluzione in pratica anche se non è formalmente corretta.

+2

Lo direbbe così: c'è molto di più in 'mmap', ma la gestione degli errori è molto più complessa rispetto all'I/O tradizionale. Questo non è necessariamente un motivo per cui stai usando l'obiettivo? ... solo essere consapevole degli spiriti che evochi ;-) –

+0

E assicurati che non ti stiano sfuggendo dal naso .. :-) –

-1

è possibile ottenere notifiche su qualsiasi modifica sul file (s), dir (s) utilizzando http://linux.die.net/man/7/inotify. potresti prendere in considerazione l'utilizzo di IN_DELETE.

+3

Queste notifiche saranno immediate come errori di pagina che l'OP sta cercando di frenare? In caso contrario, non preoccuparti. –

+0

Sembra che devi chiamare 'read()' per scoprire se ci sono state delle modifiche, ma i cambiamenti possono verificarsi tra 'read()' non restituisce nulla di interesse e il seguente accesso alla memoria. È una condizione di gara. Inoltre, la coda degli eventi potrebbe traboccare. Quindi, questa non è una soluzione. –

Problemi correlati