Quindi, facendo alcune ricerche, ho scoperto che i semafori di System V hanno un flag chiamato SEM_UNDO che può ripristinare lo stato di blocco quando il programma fallisce, ma non è garantito che funzioni.
SEM_UNDO sbloccherebbe il semaforo se il processo si arresta in modo anomalo. Se i processi si arrestano in modo anomalo a causa della corruzione della memoria condivisa, non c'è nulla che i semafori possano fare per te. Il sistema operativo non può annullare lo stato della memoria condivisa.
Se devi essere in grado di eseguire il rollback dello stato della memoria condivisa, devi implementare qualcosa da solo. Ho visto almeno due modelli che si occupano di questo.
Il primo modello prima di modificare qualsiasi cosa nella memoria condivisa stava scattando un'istantanea della struttura, salvandola in un elenco nella memoria condivisa. Se qualsiasi altro processo è stato in grado di ottenere il blocco e l'elenco non era vuoto, stava annullando qualsiasi modifica del processo in crash.
Il secondo modello consiste nel creare copie delle strutture shm nella memoria locale e mantenere il blocco bloccato per l'intera transazione. Quando viene eseguito il commit della transazione, prima di rilasciare il blocco, è sufficiente copiare le strutture dalla memoria locale nella memoria condivisa. La probabilità che l'app vada in crash durante la copia è minore e l'intervento di segnali esterni può essere bloccato utilizzando sigprocmask()
. (È meglio che il blocco nel caso sia ben suddiviso sui dati. Ad esempio, ho visto test con un set di 1000 blocchi per 10 milioni di record in shm a cui si accede da 4 processi simultanei.)
Ci sono solo poche cose che sono garantite per essere ripulite quando un programma fallisce. L'unica cosa che mi viene in mente qui sono i conteggi dei collegamenti. Un descrittore di file aperto aumenta il conteggio dei collegamenti dell'inode sottostante e una chiusura corrispondente lo diminuisce, inclusa una chiusura forzata quando il programma fallisce.
Quindi i tuoi processi potrebbero aprire tutti un file comune (non ricordare se funziona per segmenti di memoria condivisa) e potresti attivare una sorta di allarme se il conteggio diminuisce, dove non dovrebbe. Ad esempio, invece di fare una semplice attesa, i tuoi processi potrebbero eseguire un timedwait (per un secondo, ad esempio) in un ciclo e interrogare il conteggio dei collegamenti per essere avvisati quando qualcosa va storto.