SIGNALFD(2)

NOM
signalfd - Créer un descripteur de fichier pour accepter des signaux

SYNOPSIS
#include <sys/signalfd.h>

int signalfd(int fd, const sigset_t *mask, int flags);

DESCRIPTION
signalfd() crée un descripteur de fichier qui peut être utilisé pour accepter des signaux à destination de l'appelant. Ceci fournit une alternative à l'utilisation d'un gestionnaire de signal ou de sigwaitinfo(2), et à l'avantage que le descripteur de fichier peut être surveillé avec select(2), poll(2) ou epoll(7). L'argument mask indique l'ensemble des signaux que l'appelant souhaite accepter par le descripteur de fichier. Cet argument est un ensemble de signaux dont le contenu peut être initialisé en utilisant les macros décrites dans sigsetops(3). Normalement, l'ensemble de signaux devant être reçus par le descripteur de fichier devrait être bloqué avec sigprocmask(2), pour éviter que les signaux soient gérés conformément à leurs dispositions par défaut. Il n'est pas possible de recevoir les signaux SIGKILL ou SIGSTOP par un descripteur de fichier signalfd ; ces signaux sont silencieusement ignorés s'ils sont spécifiés dans mask. Si l'argument fd vaut -1, l'appel crée un nouveau descripteur de fichier et lui associe l'ensemble de signaux indiqué dans mask. Si fd ne vaut pas -1, il doit indiquer un descripteur de fichier existant et valide, et mask est utilisé pour remplacer l'ensemble de signaux associé à ce descripteur. L'argument flags n'est actuellement pas utilisé et doit être indiqué à zéro. Dans le futur, il pourrait être utilisé pour demander des fonctionnalités supplémentaires. signalfd() renvoie un descripteur de fichier qui accepte les opérations suivantes :

read(2)
    Si un ou plusieurs des signaux indiqués dans mask est en attente du processus, le tampon fourni à read(2) est utilisé pour renvoyer une ou plusieurs structures signalfd_siginfo (voir plus loin) qui décrivent les signaux. L'appel read(2) renvoie les informations pour tous les signaux qui sont en attente et qui tiennent dans le tampon fourni. Le tampon doit avoir une taille d'au moins sizeof(struct signalfd_siginfo) octets. La valeur de retour de read(2) est égale au nombre total d'octets lus.

    La conséquence d'un read(2) est que les signaux sont consommés, ainsi ils ne sont plus en attente pour le processus (c'est-à-dire qu'ils ne seront pas interceptés par des gestionnaires de signaux et ne peuvent pas être acceptés avec sigwaitinfo(2)).

    Si aucun des signaux de mask n'est en attente du processus, read(2) soit bloquera jusqu'à ce qu'un des signaux de mask soit généré pour le processus, soit échouera avec l'erreur EAGAIN si le descripteur de fichier est en mode non bloquant (via l'utilisation de l'opération F_SETFL de fcntl(2) pour définir l'attribut O_NONBLOCK).

poll(2), select(2) (et similaires)
    Le descripteur de fichier est accessible en lecture (l'argument readfds de select(2) ; l'attribut POLLIN de poll(2)) si un ou plusieurs des signaux de mask est en attente pour le processus.

    Le descripteur de fichier signalfd accepte également les autres API de multiplexage de descripteurs de fichier : pselect(2), ppoll(2) et epoll(7).

close(2)
    Lorsque le descripteur de fichier n'est plus nécessaire, il doit être fermé. Lorsque tous les descripteurs de fichier associés au même objet signalfd ont été fermés, les ressources pour cet objet sont libérées par le noyau.

  La structure signalfd_siginfo
Le format de la structure signalfd_siginfo renvoyée par read(2) à partir d'un descripteur de fichier signalfd est le suivant :
struct signalfd_siginfo {
    uint32_t ssi_signo;   /* Signal number */
    int32_t  ssi_errno;   /* Error number (unused) */
    int32_t  ssi_code;    /* Signal code */
    uint32_t ssi_pid;     /* PID of sender */
    uint32_t ssi_uid;     /* Real UID of sender */
    int32_t  ssi_fd;      /* File descriptor (SIGIO) */
    uint32_t ssi_tid;     /* Kernel timer ID (POSIX timers)
    uint32_t ssi_band;    /* Band event (SIGIO) */
    uint32_t ssi_overrun; /* POSIX timer overrun count */
    uint32_t ssi_trapno;  /* Unused */
    int32_t  ssi_status;  /* Exit status or signal (SIGCHLD) */
    int32_t  ssi_int;     /* Integer sent by sigqueue(2) */
    uint64_t ssi_ptr      /* Pointer sent by sigqueue(2) */
    uint64_t ssi_utime;   /* User CPU time consumed (SIGCHLD) */
    uint64_t ssi_stime;   /* System CPU time consumed (SIGCHLD) */
    uint64_t ssi_addr;    /* Address that generated signal
                             (for hardware-generated signals) */
    uint8_t  pad[X];      /* Pad size to 128 bytes (allow for
                              additional fields in the future) */
};
Chacun des champs de cette structure est analogue au champ de nom similaire dans la structure siginfo_t. La structure siginfo_t est décrite dans sigaction(2). Tous les champs de la structure signalfd_siginfo renvoyée ne sont pas forcément valides pour un signal particulier ; l'ensemble des champs valides peut être déterminé à partir de la valeur renvoyée dans le champ ssi_code. Ce champ est analogue au champ si_code de siginfo_t ; voir sigaction(2) pour plus de détails.

  Sémantique de fork(2)
Après un fork(2), le fils hérite d'une copie du descripteur de fichier signalfd. Le descripteur de fichier fait référence au même objet de fichier sous-jacent que le descripteur correspondant dans le parent, et les appels read(2) dans le fils renverront les informations à propos des signaux générés pour le parent (le processus qui a créé l'objet avec signalfd()).

  Sémantique de execve(2)
Tout comme un autre descripteur de fichier, un descripteur de fichier signalfd reste ouvert à travers un execve(2), à moins qu'il n'ait été marqué comme « close-on-exec » (voir fcntl(2)). Tout signal qui était disponible en lecture avant l'appel execve(2) reste disponible pour le programme nouvellement chargé. (Ceci est analogue à la sémantique traditionnelle des signaux où un signal bloqué en attente reste en attente à travers un execve(2).)

  Sémantique des threads
La sémantique des descripteurs de fichier signalfd dans un programme multithreadé reflète la sémantique standard des signaux. En d'autres mots, lorsqu'un thread lit dans un descripteur de fichier signalfd, il lira les signaux dirigés vers le thread lui-même et les signaux dirigés vers le processus (c'est-à-dire, le groupe entier des threads) (Un thread ne pourra pas lire les signaux dirigés vers d'autres threads du processus).

VALEUR RENVOYÉE
S'il réussit, signalfd() renvoie un descripteur de fichier signalfd ; ce sera soit un nouveau descripteur de fichier (si fd valait -1), soit fd si fd était un descripteur de fichier signalfd valide. S'il échoue, -1 est renvoyé et errno contient le code de l'erreur.

ERREURS

EBADF
    Le descripteur de fichier n'est pas un descripteur de fichier valide.

EINVAL
    fd n'est pas un descripteur de fichier signalfd valide ; ou flags n'est pas nul.

EMFILE
    La limite par processus du nombre total des descripteurs de fichier ouverts a été atteinte.

ENFILE
    La limite du nombre total de fichiers ouverts sur le sytème a été atteinte.

ENODEV
    Impossible de monter le périphérique anonyme d'inœud (interne).

ENOMEM
    Il n'y a pas suffisamment de mémoire pour créer un nouveau descripteur de fichier signalfd.

VERSIONS
signalfd() est disponible sous Linux depuis le noyau 2.6.22. Une prise en charge fonctionnelle est fournie dans la glibc depuis la version 2.8.

CONFORMITÉ
signalfd() est spécifique à Linux.

NOTES
L'appel système Linux sous-jacent nécessite un argument supplémentaire, size_t sizemask, qui indique la taille de l'argument mask. La fonction enveloppe signalfd() de la glibc n'a pas cet argument puisqu'elle fournit la valeur nécessaire à l'appel système sous-jacent. L'argument flags est un ajout de la glibc par rapport l'appel système sous-jacent. Un processus peut créer plusieurs descripteurs de fichier signalfd. Cela lui permet d'accepter différents signaux sur différents descripteurs de fichier. (Cela peut être utile pour la surveillance des descripteurs de fichier avec select(2), poll(2) ou epoll(7) : l'arrivée de signaux différents rendra prêts des descripteurs différents.) Si un signal apparaît dans mask pour plus d'un des descripteurs de fichier, les occurences de ce signal peuvent être lues (une fois) à partir de n'importe lequel des descripteurs.

BOGUES
Dans les noyaux antérieurs au 2.6.25, les champs ssi_ptr et ssi_int n'étaient pas renseignés avec les données accompagnant un signal envoyé par sigqueue(2).

EXEMPLE
Le programme suivant accepte les signaux SIGINT et SIGQUIT via un descripteur de fichier signalfd. Le programme se termine après avoir accepté un signal SIGQUIT. La session shell suivante montre l'utilisation du programme :
$ ./signalfd_demo
^C                    # Contrôle-C génère SIGINT
Got SIGINT
^C
Got SIGINT
^\                    # Contrôle-\ génère SIGQUIT
Got SIGQUIT
$
#include <sys/signalfd.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#define handle_error(msg) \
    do { perror(msg); exit(EXIT_FAILURE); } while (0)
int
main(int argc, char *argv[])
{
    sigset_t mask;
    int sfd;
    struct signalfd_siginfo fdsi;
    ssize_t s;
    sigemptyset(&mask);
    sigaddset(&mask, SIGINT);
    sigaddset(&mask, SIGQUIT);
    /* Bloquer les signaux pour qu'ils ne soient plus gérés
       par leurs gestionnaires par défaut */
    if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
        handle_error("sigprocmask");
    sfd = signalfd(-1, &mask, 0);
    if (sfd == -1)
        handle_error("signalfd");
    for (;;) {
        s = read(sfd, &fdsi, sizeof(struct signalfd_siginfo));
        if (s != sizeof(struct signalfd_siginfo))
            handle_error("read");
        if (fdsi.ssi_signo == SIGINT) {
            printf("Got SIGINT\n");
        } else if (fdsi.ssi_signo == SIGQUIT) {
            printf("Got SIGQUIT\n");
            exit(EXIT_SUCCESS);
        } else {
            printf("Read unexpected signal\n");
        }
    }
}

VOIR AUSSI
eventfd(2), poll(2), read(2), select(2), sigaction(2), sigprocmask(2), sigwaitinfo(2), timerfd_create(2), sigsetops(3), sigwait(3), epoll(7), signal(7)

TRADUCTION

Ce document est une traduction réalisée par Alain Portal <aportal AT univ-montp2 DOT fr> le 23 avril 2008 et révisée le 4 juillet 2008.

L'équipe de traduction a fait le maximum pour réaliser une adaptation française de qualité. La version anglaise la plus à jour de ce document est toujours consultable via la commande : « LANG=C man 2 signalfd ». N'hésitez pas à signaler à l'auteur ou au traducteur, selon le cas, toute erreur dans cette page de manuel.