2010-11-18 8 views
9

He estado viendo la implementación de puntos de cancelación de glibc/nptl, y comparándolo con POSIX, ya menos que esté equivocado, está completamente equivocado. El modelo básico utilizado es:¿Cómo se supone que se comportan los puntos de cancelación POSIX?

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

Según 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 puede verse en un programa de subproceso único cuando una llamada a una función se interrumpe por una señal y la función dada devuelve [EINTR]. Cualquiera de estos efectos secundarios ocurre antes de que se llame a los controladores de cancelación.

Mi lectura de este pasaje es que si llamo open, puedo esperar que ya sea para obtener cancelado (junto con toda mi hilo) antes de que falle para abrir un archivo, o para devolver una válida descriptor de archivo o -1 y errno 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 donde la solicitud de cancelación ocurre justo después de que syscall regrese pero antes de que ocurra el LIBC_CANCEL_RESET.

¿Estoy loco, o su implementación realmente está rota? Y si es así, ¿posix permite un comportamiento tan defectuoso (que parece inutilizar la cancelación a menos que lo posponga manualmente), o simplemente ignoran descaradamente POSIX?

Si este comportamiento se rompe, ¿cuál es la forma correcta de implementarlo sin dicha condición de carrera?

Respuesta

4

¿No es éste aclaró en el siguiente párrafo de la norma:

Sin embargo, si el hilo se suspende en un punto cancelación y el evento para la que se espera se produce antes de la solicitud de cancelación de se actúa en consecuencia, no se especifica si se responde a la solicitud de cancelación o si la solicitud de cancelación permanece pendiente y el hilo reanuda la ejecución normal .

Lo que implica que esta condición de carrera es un comportamiento perfectamente legal.

+3

¿Cómo se escribe un programa robusto con un comportamiento tan absurdo? Parece que tendrías que ajustar cada llamada a 'abrir' (y otros puntos de cancelación que pueden asignar recursos) con código para deshabilitar la cancelación, mantener la cancelación siempre desactivada y llamar manualmente a' pthread_trycancel' periódicamente, o encontrar alguna forma de cancelarla. busque y libere tales recursos (para los descriptores de archivos, es posible recorrer todos los valores, pero es bastante peligroso hacerlo en una aplicación con hilos sin algunos bloqueos pesados). –

+1

mmh, lo leí porque el hilo no puede ser cancelado todavía y debe cancelarse en el siguiente punto de cancelación (en cuyo caso, los puntos de cancelación necesitan soporte del sistema operativo, y probablemente estén rotos de la manera que R .. dice en la mayoría de los sistemas operativos). – ninjalj

+0

@ninjaj: Creo que cmeerw puede ser correcto. El pasaje dice que si (por ejemplo) el hilo se suspende esperando que 'open' vuelva, pero' open' ya ha terminado de hacer su trabajo, la implementación podría permitir la cancelación o dejarla pendiente. –

Cuestiones relacionadas