Ho riscontrato un problema con l'operazione syscall di Linux futex
(FUTEX_WAIT
), che a volte ritornava in anticipo apparentemente senza motivo. La documentazione specifica alcune condizioni che potrebbero causare un ritorno anticipato (senza uno FUTEX_WAKE
) ma tutte implicano valori di ritorno diversi da zero: EAGAIN
se il valore all'indirizzo futex non corrisponde, ETIMEDOUT
per le attese temporizzate che scadono, EINTR
quando interrotte da un segnale (non riavviato), ecc. Ma sto vedendo un valore di ritorno pari a 0. Ciò che, a parte lo FUTEX_WAKE
o la chiusura di una discussione il cui puntatore set_tid_address
punta al futex, potrebbe causare FUTEX_WAIT
restituire con un valore di ritorno di 0?Linux wex spysc di syscall con valore di ritorno 0?
Nel caso è utile, il futex particolare ero in attesa sul filo è l'indirizzo tid (fissato dal clone
syscall con CLONE_CHILD_CLEARTID
), e il filo aveva non terminato. La mia supposizione (apparentemente errata) che l'operazione FUTEX_WAIT
che restituisce 0 possa avvenire solo quando il thread terminato porta a errori gravi nella logica del programma, che da allora ho risolto in loop e riprovando anche se restituisce 0, ma ora sono curioso al perché è successo.
Ecco un test minimo:
#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);
}
}
farlo funzionare per qualche tempo, esso dovrebbe eventualmente terminare con Killed
(SIGKILL
), che è possibile solo se il filo ancora esiste quando il FUTEX_WAIT
rendimenti. codice userspace
Prima che qualcuno va assumendo questo è solo il kernel svegliare il futex prima che finisce di distruggere il filo (che potrebbe in realtà essere accadendo nel mio caso di test minima qui), si ricorda che nel mio codice originale, in realtà ho osservato eseguito correttamente nel thread dopo il FUTEX_WAIT
restituito.
Penso che potremmo aver bisogno di vedere un esempio minimo; è difficile trovare un consiglio sostanziale, dal momento che tanto è sconosciuto (posterò la mia unica intuizione come risposta temporanea in ogni caso, perché è troppo grande per un commento) – sehe
Infatti, vedrò se riesco a mettere insieme un minimo esempio. –
hm, penso che la pagina man sia piuttosto poco chiara. le condizioni sotto il valore di ritorno di "FUTEX_WAIT" qualifica le condizioni diverse da zero come condizioni di * errore *, non solo la diagnostica. Quindi in seguito dice "Nel caso di un errore, tutte le operazioni restituiscono -1 e impostano errno per indicare l'errore." D'altra parte le condizioni qui non vengono ripetute nella sezione ** ERRORI **. –