Operaciones de E/S que sobreviven al proceso: el comportamiento de io_uring tras waitpid()

Fuentes: Is There I/O After Death? What Happens to io_uring When a Process Dies

Un experimento sobre Linux 6.6.79 demuestra que las solicitudes de E/S enviadas mediante io_uring en modo ordinario pueden seguir ejecutándose después de que el proceso que las envió sea eliminado con SIGKILL y recolectado con waitpid(). En una unidad NVMe sometida a carga de lecturas o con un retardo artificial de 3 segundos mediante dm-delay, entre el 60 % y el 100 % de los bloques de 4 KiB escritos continuaron modificándose hasta tres segundos después de la reaplicación del proceso.

El autor, Evgenii Ivanov, acompaña el hallazgo de una solución práctica: abrir el dispositivo de forma independiente y adquirir un cerrojo exclusivo flock(LOCK_EX). Las solicitudes pendientes de io_uring conservan referencias a la estructura struct file del escritor, de modo que el bloqueo solo se libera cuando esas referencias se liberan en __fput(). El proceso sucesor debe intentar flock(LOCK_EX | LOCK_NB) en bucle hasta conseguirlo, lo que convierte la adquisición en una barrera de E/S fiable.

El comportamiento varía según el modo de io_uring: con IORING_SETUP_SQPOLL y con AIO nativo de Linux, el retraso se traslada a la fase de teardown del proceso y waitpid() bloquea hasta que las escrituras pendientes concluyen, funcionando también como barrera. YDB, la base de datos de Yandex, ya utiliza este protocolo de cerrojos por la misma razón. Los resultados son empíricos y válidos para el kernel probado, no una garantía portable.