POSIX / UNIX: Cómo cerrar de manera confiable un descriptor de archivo

Problema:

Después de una llamada al sistema close () que falla con EINTR o EIO, no se especifica si el archivo se ha cerrado. (http://pubs.opengroup.org/onlinepubs/9699919799/) En aplicaciones de subprocesos múltiples, volver a intentar el cierre puede cerrar archivos no relacionados abiertos por otros subprocesos. Si no se vuelve a intentar el cierre, se pueden acumular descriptores de archivos abiertos inutilizables. Una solución limpia podría implicar invocar fstat () en el descriptor de archivo recién cerrado y un mecanismo de bloqueo bastante complejo. Además, la serialización de todas las invocaciones de abrir / cerrar / aceptar / ... con un solo mutex puede ser una opción.

Estas soluciones no tienen en cuenta que las funciones de la biblioteca pueden abrir y cerrar archivos de forma incontrolable, por ejemplo, algunas implementaciones de archivos abiertos std :: thread :: hardware_concurrency () en el sistema de archivos / proc.

Las secuencias de archivos como en la sección estándar de C ++ [file.streams] no son una opción.

¿Existe un mecanismo simple y confiable para cerrar archivos en presencia de múltiples hilos?

ediciones:

Archivos normales: Si bien la mayoría de las veces no se acumularán descriptores de archivos abiertos inutilizables, dos condiciones pueden desencadenar el problema: 1. Señales emitidas a alta frecuencia por algún malware 2. Sistemas de archivos de red que pierden la conexión antes de que se vacíen las cachés.

Zócalos: según Stevens / Fenner / Rudoff, si la opción de zócalo SO_LINGER está configurada en un descriptor de archivo que hace referencia a un zócalo conectado, y durante un cierre (), el temporizador transcurre antes de que se complete la secuencia de apagado FIN-ACK, cierre () falla como parte del procedimiento común. Linux no muestra este comportamiento, sin embargo, FreeBSD sí, y también establece errno en EAGAIN. Según tengo entendido, en este caso, no se especifica si el descriptor de archivo está invalidado. Código C ++ para probar el comportamiento:http://www.longhaulmail.de/misc/close.txt La salida del código de prueba me parece una condición de carrera en FreeBSD, si no es así, ¿por qué no?

Se podrían considerar señales de bloqueo durante las llamadas para cerrar ().

Respuestas a la pregunta(3)

Su respuesta a la pregunta