¿Cómo cerrar un archivo?
Me sentí en paz con Posix después de muchos años de experiencia.
Entonces leiesta mensaje de Linus Torvalds, circa 2002:
int ret;
do {
ret = close(fd);
} while(ret == -1 && errno != EBADF);
NO.
Lo anterior es
(a) no portátil
(b) no es una práctica actual
La parte "no portátil" proviene del hecho de que (como alguien señaló), un entorno roscado en el que el núcleohace cierre el FD en caso de errores, el FD puede haber sido reutilizado válidamente (por el núcleo) para algún otro hilo, y cerrar el FD por segunda vez es un ERROR.
No solo se repite hastaEBADF
inportable, pero cualquier bucle es, debido a una condición de carrera que probablemente habría notado si no hubiera "hecho las paces" al dar por sentado tales cosas.
Sin embargo, en la implementación de la biblioteca estándar GCC C ++,basic_file_stdio.cc
, tenemos
do
__err = fclose(_M_cfile);
while (__err && errno == EINTR);
El objetivo principal de esta biblioteca es Linux, pero parece no estar prestando atención a Linus.
Por lo que he llegado a entender,EINTR
sucede solo después de una llamada al sistemabloques, lo que implica que el kernel recibió la solicitud para liberar el descriptor antes de comenzar cualquier trabajo que se interrumpiera. Entonces no hay necesidad de hacer un bucle. De hecho, elSA_RESTART
el comportamiento de la señal no se aplica aclose
y genera dicho bucle por defecto, precisamente porque no es seguro.
Este es un error de biblioteca estándar, ¿verdad? En cada archivo cerrado por una aplicación C ++.
EDITAR: Para evitar causar demasiada alarma antes de que algún gurú llegue con una respuesta, debo tener en cuenta queclose
solo parece estar permitido bloquear bajo circunstancias específicas, tal vez ninguna de las cuales se aplique a archivos normales. No tengo claros todos los detalles, pero no deberías verEINTR
declose
sin optar por algo porfcntl
osetsockopt
. Sin embargo, la posibilidad hace que el código genérico de la biblioteca sea más peligroso.