Le principal problème est que si le signal interrompt malloc()
ou d'une même fonction, l'état interne peut être temporairement incohérent alors qu'il est de déplacer les blocs de la mémoire entre le libre et utilisé de la liste, ou d'autres opérations similaires. Si le code dans le gestionnaire de signal appelle une fonction qui invoque alors malloc()
, ce qui peut complètement détruire la gestion de la mémoire.
La norme C prend une vue très conservatrice de ce que vous pouvez faire dans un gestionnaire de signal:
ISO/IEC 9899:2011 §7.14.1.1 L' signal
fonction
¶5 Si le signal se produit que sur le résultat de l'appel de l'abandon ou de soulever la fonction, la
le comportement est indéfini si le gestionnaire de signal se réfère à un objet statique ou thread
durée de stockage qui n'est pas un lock-atomique sans autre objet que par l'attribution d'une valeur à une
objet déclaré en tant que volatile sig_atomic_t
, ou le gestionnaire de signal appelle une fonction
de la bibliothèque standard, autres que l' abort
de la fonction, l' _Exit
de la fonction, la
quick_exit
de la fonction, ou l' signal
fonction avec le premier argument égal à la
numéro de signal correspondant au signal qui a provoqué l'invocation de la gestionnaire.
En outre, si un tel appel à l' signal
résultats de la fonction d'un SIG_ERR
retour, l'
la valeur de errno
est indéterminée.252)
252) 252) Si un signal est généré par un asynchrones gestionnaire de signal, le comportement est indéfini.
POSIX est beaucoup plus généreux sur ce que vous pouvez faire dans un gestionnaire de signal.
Signal Concepts dit:
Si le processus est multi-thread, ou si le processus est monothread et un gestionnaire de signal est exécutée que sur le résultat de:
Le processus appelant abort()
, raise()
, kill()
, pthread_kill()
ou sigqueue()
pour générer un signal qui n'est pas bloqué
En attente d'un signal non bloqué et être livrés avant l'appel débloqués il retourne
le comportement est indéfini si le gestionnaire de signal se réfère à un objet autre que errno avec statique de la durée de stockage autres que par affectation d'une valeur à un objet déclaré en tant que volatile sig_atomic_t
, ou si le gestionnaire de signal appelle une fonction définie dans la présente norme autre que l'une des fonctions énumérées dans le tableau suivant.
Le tableau suivant définit un ensemble de fonctions qui doivent être async un signal fort. Par conséquent, les applications peuvent les invoquer, sans restriction, à partir du signal-la capture de fonctions:
_Exit() fexecve() posix_trace_event() sigprocmask()
_exit() fork() pselect() sigqueue()
abort() fstat() pthread_kill() sigset()
accept() fstatat() pthread_self() sigsuspend()
access() fsync() pthread_sigmask() sleep()
aio_error() ftruncate() raise() sockatmark()
aio_return() futimens() read() socket()
aio_suspend() getegid() readlink() socketpair()
alarm() geteuid() readlinkat() stat()
bind() getgid() recv() symlink()
cfgetispeed() getgroups() recvfrom() symlinkat()
cfgetospeed() getpeername() recvmsg() tcdrain()
cfsetispeed() getpgrp() rename() tcflow()
cfsetospeed() getpid() renameat() tcflush()
chdir() getppid() rmdir() tcgetattr()
chmod() getsockname() select() tcgetpgrp()
chown() getsockopt() sem_post() tcsendbreak()
clock_gettime() getuid() send() tcsetattr()
close() kill() sendmsg() tcsetpgrp()
connect() link() sendto() time()
creat() linkat() setgid() timer_getoverrun()
dup() listen() setpgid() timer_gettime()
dup2() lseek() setsid() timer_settime()
execl() lstat() setsockopt() times()
execle() mkdir() setuid() umask()
execv() mkdirat() shutdown() uname()
execve() mkfifo() sigaction() unlink()
faccessat() mkfifoat() sigaddset() unlinkat()
fchdir() mknod() sigdelset() utime()
fchmod() mknodat() sigemptyset() utimensat()
fchmodat() open() sigfillset() utimes()
fchown() openat() sigismember() wait()
fchownat() pause() signal() waitpid()
fcntl() pipe() sigpause() write()
fdatasync() poll() sigpending()
Toutes les fonctions qui ne sont pas dans le tableau ci-dessus sont considérés comme dangereux à l'égard de signaux. En présence de signaux, toutes les fonctions définies par le présent volume de POSIX.1-2008 date doit se comporter comme défini lorsqu'il est appelé à partir de ou interrompu par un signal de la capture de la fonction, avec une seule exception: lorsqu'un signal interrompt un dangereux la fonction et le signal de la capture appels de fonctions dangereuses de la fonction, le comportement est indéfini.
Les opérations d'obtenir la valeur de errno et des opérations qui lui affecter une valeur de errno est asynchrone par un signal fort.
Lorsqu'un signal est transmis à un fil, si l'action de ce signal indique la résiliation, de l'arrêter ou de continuer, l'ensemble du processus doit être dénoncé, arrêté ou poursuivi, respectivement.
Cependant, l' printf()
famille de fonctions est absente de cette liste et ne peut pas être appelé en toute sécurité à partir d'un gestionnaire de signal.
En conséquence, vous ne finissent soit à l'aide de write()
sans la mise en forme du soutien fourni par printf()
et al, ou vous finissez par la définition d'un indicateur de test (périodiquement) dans les endroits appropriés dans votre code. Cette technique est parfaitement incarné dans la réponse par Grijesh Chauhan.