es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo interrumpir la lectura síncrona de inotify?

Quiero tener un hilo de fondo que esté constantemente leyendo el descriptor de archivo de inotify y manejando todos los eventos. Obviamente, también necesito una forma de interrumpir este hilo cuando se cierre la aplicación. Pensé que la forma más sencilla de lograr esto es cerrar el descriptor de archivo de inotify, lo cual hará que la función read devuelva -EBADF.

Desafortunadamente, esto no siempre es el caso. A veces (usualmente después de ~200 iteraciones) este método se bloquea, el hilo de fondo se queda atascado en la función read. Noté que adjuntar y desvincular un depurador es suficiente para despertar al hilo y permitirle finalizar. La salida de strace -f ./MyApp ilustra el problema. Normalmente, la función read se reanuda después del close, pero esporádicamente no lo hace.

Código del reproducidor mínimo a continuación
“`c++
#include <stdio.h>
#include <sys inotify.h="">
#include <thread>
#include <unistd.h>

void thr(int fd) {
while (true) {
const static int bufferSize = 1024;
char buffer[bufferSize];
int length = read(fd, buffer, bufferSize);
if (length < 0) {
perror("read failed");
break;
}

<pre><code> // … Manejar los eventos, no importa.
}
printf("Saliendo del hilo de manera correcta\n");
</code></pre>

}

int main() {
int fd = inotify_init();
int wd = inotify_add_watch(fd, ".", IN_CREATE | IN_DELETE | IN_MOVE | IN_MODIFY);

<pre><code>std::thread t{thr, fd};

inotify_rm_watch(fd, wd);
close(fd);

t.join();
</code></pre>

}
“`

¿Qué está sucediendo dentro de la llamada de read en espera? ¿Mi enfoque es incorrecto? ¿Debería enviar alguna señal al hilo para despertarlo?</unistd.h></stdio.h>

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    La llamada read colgada se debe a una condición de carrera entre la llamada inotify_rm_watch y la llamada read. Cuando se realiza la llamada inotify_rm_watch, se elimina la vigilancia de la instancia de inotify, pero el hilo de fondo aún puede estar bloqueado en la llamada read. Si ocurre un evento en el descriptor de archivo antes de que se realice la llamada close, el hilo se desbloqueará y continuará ejecutándose. Sin embargo, si no ocurren eventos, el hilo permanecerá bloqueado para siempre, esperando un evento en un descriptor de archivo que se ha cerrado.

    Un enfoque para resolver este problema es utilizar un descriptor de archivo adicional para señalar al hilo que debe salir. En lugar de cerrar el descriptor de archivo inotify para interrumpir el hilo, puede crear una tubería y agregar el extremo de lectura de la tubería al conjunto de descriptores de archivo monitoreados por la llamada select o poll que está esperando eventos en el descriptor de archivo inotify. Cuando se cierra el extremo de escritura de la tubería, la llamada select o poll devolverá el indicador POLLHUP, indicando que el extremo de lectura de la tubería se puede cerrar de forma segura y el hilo puede salir.

Comments are closed.