¿Cómo se supone que deben comportarse los puntos de cancelación POSIX?

He estado mirando la implementación de puntos de cancelación de glibc / nptl y comparándola con POSIX, y a menos que me equivoque, está completamente mal. El modelo básico utilizado es:

int oldtype = LIBC_ASYNC_CANCEL(); /* switch to asynchronous cancellation mode */
int result = INLINE_SYSCALL(...);
LIBC_CANCEL_RESET(oldtype);

De acuerdo con POSIX:

Los efectos secundarios de actuar sobre una solicitud de cancelación mientras está suspendido durante una llamada de una función son los mismos que los efectos secundarios que se pueden ver en un programa de subproceso único cuando una señal interrumpe una llamada a una función y la función devuelve [EINTR]. Cualquiera de estos efectos secundarios se produce antes de que se llame a los controladores de limpieza de cancelación.

Mi lectura de este pasaje es que si llamoopenPuedo esperarya sea para cancelar (junto con todo mi hilo) antes de que no se pueda abrir un archivo,o para devolver un descriptor de archivo válido o -1 yerrno valor, pero nunca para crear un nuevo descriptor de archivo y luego perderlo en el vacío. Por otro lado, la implementación glibc / nptl de los puntos de cancelación parece permitir una condición de carrera en la que la solicitud de cancelación ocurre justo después de que regrese la llamada al sistema pero antesLIBC_CANCEL_RESET tiene lugar.

¿Estoy loco o su implementación está realmente rota? Y si es así, ¿POSIX permite un comportamiento tan roto (que parece hacer que la cancelación sea completamente inutilizable a menos que la difiera manualmente), o simplemente están ignorando descaradamente a POSIX?

Si este comportamiento está roto, ¿cuál es la forma correcta de implementarlo sin una condición de carrera?

Respuestas a la pregunta(1)

Su respuesta a la pregunta