Si scopre che non c'è un modo per recuperare in modo affidabile il semaforo. Certo, chiunque può post_sem()
al semaforo indicato per far aumentare di nuovo il conteggio oltre lo zero, ma come sapere quando è necessario un tale recupero? L'API fornita è troppo limitata e non indica in alcun modo quando ciò è avvenuto.
Attenzione anche agli strumenti ipc disponibili -- gli strumenti comuni ipcmk
, ipcrm
e ipcs
sono solo per i semafori SysV obsoleti. In particolare non funzionano con i nuovi semafori POSIX.
Ma sembra che ci siano altre cose che possono essere utilizzate per bloccare le cose, che il sistema operativo rilascia automaticamente quando un'applicazione muore in un modo che non può essere catturato in un gestore di segnale. Due esempi:un socket in ascolto associato a una porta particolare o un blocco su un file specifico.
Ho deciso che il blocco su un file è la soluzione di cui avevo bisogno. Quindi, invece di un sem_wait()
e sem_post()
call, sto usando:
lockf( fd, F_LOCK, 0 )
e
lockf( fd, F_ULOCK, 0 )
Quando l'applicazione esce in qualsiasi modo, il file viene chiuso automaticamente, rilasciando anche il blocco del file. Altre app client in attesa del "semaforo" sono quindi libere di procedere come previsto.
Grazie per l'aiuto, ragazzi.
Usa un file di blocco invece di un semaforo, proprio come la soluzione di @ Stéphane ma senza le chiamate flock(). Puoi semplicemente aprire il file usando un lucchetto esclusivo:
//call to open() will block until it can obtain an exclusive lock on the file.
errno = 0;
int fd = open("/tmp/.lockfile",
O_CREAT | //create the file if it's not present.
O_WRONLY | //only need write access for the internal locking semantics.
O_EXLOCK, //use an exclusive lock when opening the file.
S_IRUSR | S_IWUSR); //permissions on the file, 600 here.
if (fd == -1) {
perror("open() failed");
exit(EXIT_FAILURE);
}
printf("Entered critical section.\n);
//Do "critical" stuff here.
//exit the critical section
errno = 0;
if (close(fd) == -1) {
perror("close() failed");
exit(EXIT_FAILURE);
}
printf("Exited critical section.\n");
Questo è un problema tipico quando si gestiscono i semafori. Alcuni programmi utilizzano un unico processo per gestire l'inizializzazione/cancellazione del semaforo. Di solito questo processo fa solo questo e nient'altro. Le altre applicazioni possono attendere finché il semaforo non è disponibile. L'ho visto fare con l'API di tipo SYSV, ma non con POSIX. Simile a 'Duck ' menzionato, usando il flag SEM_UNDO nella tua chiamata semop().
Ma, con le informazioni che hai fornito ti suggerirei di non usare i semafori. Soprattutto se il tuo processo è in pericolo di essere ucciso o andare in crash. Prova a usare qualcosa che il sistema operativo pulirà automaticamente per te.