Me he encontrado con un problema con el sistema operativo futex
de Linux (operación FUTEX_WAIT
) que algunas veces regresa temprano aparentemente sin causa. La documentación especifica ciertas condiciones que pueden hacer que regrese pronto (sin un FUTEX_WAKE
) pero todas involucran valores de retorno distintos de cero: EAGAIN
si el valor en la dirección futex no coincide, ETIMEDOUT
para tiempos esperados que expiran, EINTR
cuando se interrumpe por una señal (no reinicio), etc. Pero veo un valor de retorno de 0. Lo que, aparte de FUTEX_WAKE
o la terminación de un hilo cuyo puntero set_tid_address
apunta al futex, podría causar que FUTEX_WAIT
devuelva con un valor de retorno de 0?Linux futex syscall spurious Wakes con valor de retorno 0?
En caso de que sea útil, el futex particular, que estaba esperando en es la dirección tid hilo (establecido por el clone
syscall con CLONE_CHILD_CLEARTID
), y el hilo tenía no terminado. Mi (aparentemente incorrecta) suposición de que la operación FUTEX_WAIT
que retorna 0 solo podría ocurrir cuando el hilo terminó conduce a errores serios en la lógica del programa, que he reparado desde entonces mediante bucles y reintentando incluso si devuelve 0, pero ahora tengo curiosidad por a por qué sucedió
Aquí es un caso de prueba mínima:
#define _GNU_SOURCE
#include <sched.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <linux/futex.h>
#include <signal.h>
static char stack[32768];
static int tid;
static int foo(void *p)
{
syscall(SYS_getpid);
syscall(SYS_getpid);
syscall(SYS_exit, 0);
}
int main()
{
int pid = getpid();
for (;;) {
int x = clone(foo, stack+sizeof stack,
CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND
|CLONE_THREAD|CLONE_SYSVSEM //|CLONE_SETTLS
|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID
|CLONE_DETACHED,
0, &tid, 0, &tid);
syscall(SYS_futex, &tid, FUTEX_WAIT, x, 0);
/* Should fail... */
syscall(SYS_tgkill, pid, tid, SIGKILL);
}
}
se deja correr por un tiempo, por lo que finalmente debe terminar con Killed
(SIGKILL
), que sólo es posible si el hilo todavía existe cuando el FUTEX_WAIT
devoluciones.
Antes de que cualquiera asuma que esto es solo el núcleo despertando el futex antes de que termine destruyendo el hilo (lo que de hecho podría estar ocurriendo en mi caso de prueba mínimo aquí), observo que en mi código original corriendo en el hilo bien después de FUTEX_WAIT
devuelto.
Creo que es posible que necesitemos ver un ejemplo mínimo; es difícil encontrar consejos importantes, ya que se desconoce mucho (publicaré mi presentimiento como una respuesta temporal de todos modos, porque es un gran comentario) – sehe
De hecho, veré si puedo armar un mínimo ejemplo. –
hm, creo que la página del manual no está clara. las condiciones bajo el valor de retorno de 'FUTEX_WAIT' califica las condiciones no nulas como condiciones de * error *, no solo diagnósticos. Luego, más tarde dice "En caso de error, todas las operaciones devuelven -1 y configuran errno para indicar el error". Por otro lado, las condiciones aquí no se repiten en la sección ** ERRORES **. –