Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

A handler installed with `SA_RESTART` does not restart the interrupted syscall

Aperta
#418 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 3 giorni

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
25/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
c, linux

Direzione di ricerca

Start with syscall_restart_arm in src/syscall/proc.h, which today handles only execve on the thread group leader, and read the comment explaining why a signal delivered before resume cancels it. The fix depends on #384, since the handler frame carries the wire value in X8 rather than the syscall number. Build the reproducer from the issue, which should match Linux for FUTEX_WAIT and a pipe read (rc=0 and rc=1 respectively) instead of EINTR.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Linux restarts a syscall that a signal interrupted when the handler was installed with SA_RESTART and the syscall is one of the restartable ones in signal(7): read on a pipe or socket, futex FUTEX_WAIT without a timeout, wait4, accept and so on. elfuse returns EINTR to the guest instead. Measured for the two below; the others are untested.

The dispatcher has a restart path (syscall_restart_arm in src/syscall/proc.h), but it serves only an execve handed to the thread group leader, and a signal delivered before the guest resumes cancels it. The comment there gives the reason: the frame the handler returns through carries the wire value in X8 and not the syscall number, so a rewound PC would re-execute a different syscall. That is #384, which this depends on.

Reproducer: a SIGUSR1 handler installed with SA_RESTART, one thread parked in each wait, pthread_kill(SIGUSR1) at it, then the wait released (a FUTEX_WAKE after storing 1, a one-byte write).

#include <errno.h>
#include <linux/futex.h>
#include <pthread.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/syscall.h>
#include <unistd.h>

static uint32_t word;
static int pfd[2];
static volatile int handled;

static void on(int s)
{
    (void) s;
    handled++;
}

static void *w_futex(void *a)
{
    (void) a;
    long r = syscall(SYS_futex, &word, FUTEX_WAIT, 0, NULL, NULL, 0);
    printf("futex FUTEX_WAIT: rc=%ld errno=%d\n", r, r < 0 ? errno : 0);
    return NULL;
}

static void *w_read(void *a)
{
    (void) a;
    char c;
    long r = read(pfd[0], &c, 1);
    printf("read on a pipe:   rc=%ld errno=%d\n", r, r < 0 ? errno : 0);
    return NULL;
}

static void rel_futex(void)
{
    word = 1;
    syscall(SYS_futex, &word, FUTEX_WAKE, 1, NULL, NULL, 0);
}

static void rel_read(void)
{
    write(pfd[1], "x", 1);
}

static void run(void *(*fn)(void *), void (*release)(void))
{
    pthread_t t;
    pthread_create(&t, NULL, fn, NULL);
    usleep(200000);
    pthread_kill(t, SIGUSR1);
    usleep(300000);
    release();
    pthread_join(t, NULL);
}

int main(void)
{
    struct sigaction sa;
    memset(&sa, 0, sizeof sa);
    sa.sa_handler = on;
    sa.sa_flags = SA_RESTART;
    sigaction(SIGUSR1, &sa, NULL);
    pipe(pfd);
    run(w_futex, rel_futex);
    run(w_read, rel_read);
    printf("handler ran %d times\n", handled);
    return 0;
}
wait elfuse Linux 6.12 under qemu
futex(FUTEX_WAIT), no timeout rc=-1 errno=4 rc=0
read on an empty pipe rc=-1 errno=4 rc=1

The handler runs both times on both.

The waits signal(7) lists as never restarted (nanosleep, select, poll, epoll_wait among them) are out of scope: EINTR is right for those.

Lingua principale
C
Stelle
273
Fork
29
Merge medio
2g 10h
PR unite (30g)
17

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di sysprog21/elfuse

Tutte le issue di sysprog21/elfuse

Issue simili

Altre issue su C

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.