Pregunta

Win32's CreateFile tiene FILE_FLAG_DELETE_ON_CLOSE , pero estoy en Linux.

Deseo abrir un archivo temporal que siempre se eliminará al finalizar el programa. Podría entender que en el caso de un bloqueo del programa puede no ser práctico garantizar esto, pero en cualquier otro caso me gustaría que funcionara.

Sé sobre RAII. Sé sobre señales. Sé sobre atexit (3) . Sé que puedo abrir el archivo y eliminarlo de inmediato y el archivo permanecerá accesible hasta que se cierre el descriptor del archivo (que incluso maneja un bloqueo). Ninguno de estos parece una solución completa y directa:

  1. RAII: estado allí, hecho eso: tengo un objeto cuyo destructor elimina el archivo, pero no se llama al destructor si el programa termina con una señal.
  2. señales: estoy escribiendo una biblioteca de bajo nivel que hace que registrar un controlador de señal sea una propuesta difícil. Por ejemplo, ¿qué pasa si la aplicación usa señales en sí misma? No quiero pisar ningún dedo del pie. Podría considerar un uso inteligente de sigaction (2) para hacer frente ... pero aún no he pensado lo suficiente en esta posibilidad.
  3. atexit (3) : aparentemente inútil, ya que no se llama durante la terminación anormal (por ejemplo, a través de una señal).
  4. preventivo unlink (2) : esto es bastante bueno, excepto que necesito que el archivo permanezca visible en el sistema de archivos (de lo contrario, el sistema es más difícil de monitorear / solucionar)

¿Qué harías aquí?

Explicación adicional

Eliminé un detalle en mi publicación original que ahora me doy cuenta de que debería haber incluido. El " archivo " en este caso no es estrictamente un archivo normal, sino que es una cola de mensajes POSIX. Lo creo a través de mq_open () . Se puede cerrar mediante mq_close () o close () (el primero es un alias para el segundo en mi sistema). Se puede eliminar del sistema a través de mq_unlink () . Todo esto lo hace análogo a un archivo normal, excepto que no puedo elegir el directorio en el que reside el archivo. Esto hace que la respuesta más popular actual (colocar el archivo en / tmp ) no funcione, porque el " archivo " es creado por el sistema en un sistema de archivos virtual con capacidad muy limitada. (He montado el sistema de archivos virtual en / dev / mqueue , siguiendo el ejemplo en man mq_overview ).

Esto también explica por qué necesito que el nombre permanezca visible (haciendo que el enfoque de desvinculación inmediata no funcione): el " archivo " debe compartirse entre dos o más procesos.

¿Fue útil?

Solución

El requisito de que el nombre permanezca visible mientras se ejecuta el proceso hace que sea difícil de lograr. ¿Puedes volver a visitar ese requisito?

Si no, entonces probablemente no haya una solución perfecta. Consideraría combinar una estrategia de manejo de señal con lo que sugiere Kamil Kisiel. Puede realizar un seguimiento de los controladores de señal instalados antes de instalar sus controladores de señal. Si el controlador predeterminado es SIG_IGN, normalmente no instalarías tu propio controlador; si es SIG_DFL, recordarías eso; si se trata de algo más, un controlador de señal definido por el usuario, recordará ese puntero e instalará el suyo. Cuando llamaron a su controlador, haría lo que fuera necesario y luego llamaría al controlador recordado, encadenando así los controladores. También instalarías un controlador atexit (). También documentaría que hace esto y las señales para las cuales lo hace.

Tenga en cuenta que el manejo de la señal es una estrategia imperfecta; SIGKILL no se puede capturar, y no se llamará al controlador atexit (), y el archivo se quedará.

La sugerencia de David Segond, un daemon de nombre de archivo temporal, es interesante. Para procesos simples, es suficiente; si el proceso que solicita el archivo temporal se bifurca y espera que el niño sea el dueño del archivo a partir de entonces (y salga), entonces el demonio tiene un problema para detectar cuándo el último proceso que lo usa muere, porque no conoce automáticamente los procesos que lo tienen abierto.

Otros consejos

Si solo está creando un archivo temporal, simplemente créelo en / tmp o en un subdirectorio del mismo. Luego, haga un gran esfuerzo para eliminarlo cuando lo haga a través de atexit (3) o similar. Siempre que use nombres únicos seleccionados a través de mkstemp (3) o similar, incluso si no se elimina debido a un bloqueo del programa, no corre el riesgo de leerlo nuevamente en ejecuciones posteriores u otras condiciones similares .

En ese punto, es solo un problema a nivel de sistema mantener limpio / tmp . La mayoría de las distribuciones lo borran durante el arranque o el apagado, o ejecutan un cronjob regular para eliminar archivos antiguos.

Tal vez alguien ya sugirió esto, pero no puedo detectarlo, dados todos sus requisitos, lo mejor que puedo pensar es que el nombre de archivo se comunique de alguna manera a un proceso padre, como un script de inicio, que limpiar después de que el proceso muere, si no pudo hacerlo. Tal vez esto se conoce principalmente como un perro guardián, pero luego con el caso de uso más común agregado para matar y / o reiniciar el proceso cuando de alguna manera falla.

Si su proceso padre también muere, no tiene suerte, pero la mayoría de los entornos de script son bastante robustos y rara vez mueren a menos que el script esté roto, lo que a menudo es más fácil de mantener correcto que un programa.

En el pasado, he creado un " administrador de archivos temporales " que realizaba un seguimiento de los archivos temporales.

Uno solicitaría un nombre de archivo temporal al administrador y este nombre se registró.

Una vez que ya no necesita el nombre del archivo temporal, informa al administrador y el nombre del archivo no está registrado.

Al recibir una señal de finalización, se destruyeron todos los archivos temporales registrados.

Los nombres de archivo temporales se basaban en UUID para evitar colisiones.

Podría tener la bifurcación del proceso después de crear el archivo, y luego esperar a que el hijo se cierre, y luego el padre puede desvincular el archivo y salir.

Me acabo de unir a stackoverflow y te encontré aquí :)

Si su problema es administrar archivos mq y evitar que se acumulen, realmente no necesita garantizar la eliminación del archivo al finalizar. Si solo desea que se acumulen archivos inútiles, entonces llevar un diario puede ser todo lo que necesita. Agregue una entrada al archivo de diario después de que se abre un mq, otra entrada cuando está cerrado y cuando se inicializa su biblioteca, verifique la inconsistencia en el diario y tome las medidas necesarias para corregir la inconsistencia. Si le preocupa bloquearse cuando se llama a mq_open / mq_close , también puede agregar una entrada de diario justo antes de que se invoquen esas funciones.

  • Tenga un directorio de contabilidad para archivos temporales en su directorio de puntos.
  • Al crear un archivo temporal, primero cree un archivo de contabilidad en el directorio de contabilidad que contiene la ruta o UUID a su futuro archivo temporal.
  • Cree ese archivo temporal.
  • Cuando se elimina el archivo temporal, elimine el archivo de contabilidad.
  • Cuando se inicia el programa, escanee el directorio de contabilidad en busca de archivos que contengan rutas a archivos temporales e intente eliminarlos si los encuentra, elimine los archivos de contabilidad.
  • (Registre ruidosamente si falla algún paso).

No veo formas de hacerlo de una manera más simple. Esta es la base que debe seguir cualquier programa de calidad de producción; +500 líneas fácilmente.

¿Realmente necesita que el nombre permanezca visible?

Suponga que toma la opción de desvincular inmediatamente el archivo. Entonces:

  •   

    desvinculación preventiva (2): esto es bastante bueno, excepto que necesito que el archivo permanezca visible en el sistema de archivos (de lo contrario, el sistema es más difícil de monitorear / solucionar problemas).

    Todavía puede depurar en un archivo eliminado, ya que seguirá siendo visible en / proc / $ pid / fd / . Mientras conozca los pids de sus procesos, enumerar sus archivos abiertos debería ser fácil.

  •   

    los nombres deben permanecer visibles durante la operación normal porque se comparten entre programas.

    Aún puede compartir el archivo abierto eliminado entre procesos pasando el descriptor de archivo por los sockets de dominio Unix. Consulte Forma portátil de pasar descriptor de archivo entre diferentes procesos para más información.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top