Resulta que no hay una forma de recuperar el semáforo de manera confiable. Claro, cualquiera puede post_sem()
al semáforo nombrado para que el conteo aumente más allá de cero nuevamente, pero ¿cómo saber cuándo se necesita tal recuperación? La API proporcionada es demasiado limitada y no indica de ninguna manera cuándo sucedió esto.
Tenga cuidado con las herramientas ipc también disponibles:las herramientas comunes ipcmk
, ipcrm
y ipcs
son solo para los semáforos SysV obsoletos. Específicamente, no funcionan con los nuevos semáforos POSIX.
Pero parece que hay otras cosas que se pueden usar para bloquear cosas, que el sistema operativo libera automáticamente cuando una aplicación muere de una manera que no puede ser capturada en un controlador de señal. Dos ejemplos:un socket de escucha vinculado a un puerto en particular o un bloqueo en un archivo específico.
Decidí que el bloqueo de un archivo es la solución que necesitaba. Así que en lugar de un sem_wait()
y sem_post()
llama, estoy usando:
lockf( fd, F_LOCK, 0 )
y
lockf( fd, F_ULOCK, 0 )
Cuando la aplicación sale de alguna manera, el archivo se cierra automáticamente, lo que también libera el bloqueo del archivo. Otras aplicaciones cliente que esperan el "semáforo" pueden continuar libremente como se esperaba.
Gracias por la ayuda, chicos.
Use un archivo de bloqueo en lugar de un semáforo, como la solución de @Stéphane pero sin las llamadas a flock(). Simplemente puede abrir el archivo usando un bloqueo exclusivo:
//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");
Este es un problema típico cuando se manejan semáforos. Algunos programas utilizan un único proceso para gestionar la inicialización/eliminación del semáforo. Por lo general, este proceso hace solo esto y nada más. Sus otras aplicaciones pueden esperar hasta que el semáforo esté disponible. He visto esto hecho con la API de tipo SYSV, pero no con POSIX. Similar a lo que 'Duck ' mencionado, usando el indicador SEM_UNDO en su llamada semop().
Pero, con la información que ha proporcionado, le sugiero que no use semáforos. Especialmente si su proceso está en peligro de morir o bloquearse. Intente usar algo que el sistema operativo limpiará automáticamente por usted.