¿Puede un programa llamar a fflush() en el mismo ARCHIVO* simultáneamente?


Puede suceder algo malo (como comportamiento indefinido, corrupción de archivos, etc.) si varios hilos simultáneamente llaman fflush() en la misma variable FILE*?

Aclaración: No me refiero a escribir el archivo simultáneamente. Sólo me refiero a tirarlo al mismo tiempo.

Los subprocesos no leen ni escriben el archivo simultáneamente (solo escriben el archivo dentro de una sección crítica, un subproceso a la vez). Solo se limpian fuera de la sección crítica, para liberar la sección crítica más pronto para deje que los demás hagan el otro trabajo (excepto la escritura de archivos).

Aunque puede suceder que un hilo esté escribiendo el archivo (dentro de la sección crítica), mientras que otro hilo(s) esté limpiando el archivo (fuera de la sección crítica).

Author: Serge Rogatch, 2016-08-20

5 answers

Corrientes en C1 son seguros para subprocesos2. Se requieren funciones para bloquear la transmisión antes de acceder a ella3.

La función fflush es segura para subprocesos y se puede llamar desde cualquier subproceso en cualquier momento, siempre que el flujo sea un flujo de salida o un flujo de actualización4.


1 Según el estándar actual, que es C11.

2 (Citado de: ISO/IEC 9899: 201x 7.21.3 Flujos 7)
Cada flujo tiene un bloqueo asociado que es se utiliza para evitar carreras de datos cuando múltiples los subprocesos de ejecución acceden a una secuencia y restringen el entrelazamiento de las operaciones de secuencia realizado por múltiples hilos. Solo un hilo puede sostener este bloqueo a la vez. La cerradura es reentrante: un solo hilo puede mantener el bloqueo varias veces a la vez.

3 (Citado de: ISO/IEC 9899: 201x 7.21.3 Streams 8)
Todas las funciones que leen, escriben, posicionan o consultan la posición de un flujo bloquean el flujo antes de acceder a él. Le suelte el bloqueo asociado con la secuencia cuando el acceso es completo. reentrante: un solo hilo puede mantener el bloqueo varias veces a la vez.

4 (Citado de: ISO/IEC 9899: 201x 7.21.5.2 La función fflush 2)
Si flujo apunta a un flujo de salida o un flujo de actualización en el que el más reciente la operación no fue introducida, la función fflush causa cualquier dato no escrito para esa secuencia para ser entregado al entorno host para ser escrito en el archivo; de lo contrario, el el comportamiento es indefinido.

 39
Author: 2501,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-23 19:22:46

El POSIX.las funciones del lenguaje 1 y C que operan en flujos de caracteres (representados por punteros a objetos de tipo FILE) son requeridas por POSIX.1c se implementará de tal manera que se logre la reentrada (véase ISO/IEC 9945:1-1996, §8.2).

Este requisito tiene un inconveniente; impone multas sustanciales de rendimiento debido a la sincronización que debe ser incorporada en las implementaciones de las funciones en aras de la reentrada. POSIX.1c aborda esta compensación entre reentrada (seguridad) y rendimiento mediante la introducción de versiones de alto rendimiento, pero no reentrantes (potencialmente inseguras), de las siguientes funciones de E/S estándar del lenguaje C: getc (), getchar (), putc () y putchar (). Las versiones no reentrantes se llaman getc_unlocked(), y así sucesivamente, para enfatizar su inseguridad.

Tenga en cuenta, sin embargo, como otros han señalado: Muchos sistemas populares (incluyendo Windows y Android) no son compatibles con POSIX.

 12
Author: geocar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-20 13:56:13

No se supone que llame a fflush() en un flujo de entrada, invoca un comportamiento indefinido, por lo que asumiré que el flujo está abierto en modo de escritura o actualización.

Si la secuencia está abierta en modo actualización ("w+" o "r+"), la última operación no debe ser una lectura cuando llame a fflush(). Dado que el flujo se utiliza en varios hilos de forma asíncrona, sería difícil garantizar esto sin alguna forma de comunicación entre procesos y sincronización o bloqueo si realiza alguna lectura. Todavía hay un razón válida para abrir el archivo en modo de actualización, pero asegúrese de no hacer ninguna lectura después de iniciar el hilo fflush.

fflush() no modifica la posición actual. Simplemente hace que cualquier salida en búfer se escriba en el sistema. Los flujos generalmente están protegidos por un bloqueo, por lo que llamar a fflush() en un subproceso no debe ensuciar la salida realizada por otro subproceso, pero puede cambiar el tiempo de las escrituras del sistema. Si varios hilos de salida el mismo FILE*, el orden en el que el el interleaving ocurre es indeterminado de todos modos. Además, si utiliza fseek() es hilos diferentes para el mismo flujo, debe usar un bloqueo propio para garantizar la coherencia entre fseek() y la siguiente salida.

Aunque parece correcto hacerlo, probablemente no se recomienda. En su lugar, podría llamar a fflush() después de las operaciones de escritura en cada subproceso, antes de liberar el bloqueo.

 9
Author: chqrlie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-27 08:22:41

Respuesta bastante simple, es posible que no lo haga, ya que el archivo tiene una sola "posición actual". ¿Cómo sigo? ¿Se abre el archivo para acceso secuencial o aleatorio? En este último caso, podría abrirlo varias veces (una para cada subproceso) y, sin embargo, idear formas de mantener la estructura del archivo consistente.

 1
Author: Constantine Georgiou,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-20 11:58:27

La respuesta real parece ser que los flujos están (destinados a ser) seguros para los hilos, pero, si ese no fuera el caso, su problema podría ser que fflush ocurre (fuera de un bloqueo) mientras que otro hilo está escribiendo (dentro de una sección crítica).

Como tal, trabajaría con el modelo de la máquina virtual contra la que está codificando y pondría el fflush() dentro de una sección crítica también.

 0
Author: Mark Hurd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-24 05:03:57