Ce n'est pas un signal qui interrompt un appel système bloquant; c'est la livraison du signal au gestionnaire enregistré (qui n'a pas été installé avec les drapeaux SA_RESTART) qui provoque l'interruption d'un appel système bloquant.
Voici un exemple. La première fonction est un gestionnaire de signal vide (forme longue, donc approprié pour les deux signaux POSIX, ainsi que les signaux en temps réel SIGRTMIN+0
à SIGRTMAX-1
). La deuxième fonction est l'installateur du gestionnaire.
#define _POSIX_C_SOURCE 200809L
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
static void empty_handler(int signum, siginfo_t *info, void *context)
{
}
/* Install empty handler for the specified signal.
* Returns 0 if success, errno error code otherwise.
*/
static int install_empty_handler(const int signum)
{
struct sigaction act;
memset(&act, 0, sizeof act);
sigemptyset(&act.sa_mask);
act.sa_sigaction = empty_handler;
act.sa_flags = SA_SIGINFO;
if (sigaction(signum, &act, NULL) == -1)
return errno;
return 0;
}
Dans votre main()
, disons que vous exécutez
if (install_empty_handler(SIGUSR1)) {
fprintf(stderr, "Cannot install signal handler: %s.\n", strerror(errno));
return EXIT_FAILURE;
}
avant de créer des threads. (Les gestionnaires de signal sont toujours assignés à tous les threads d'un processus, vous ne pouvez pas définir un gestionnaire pour un thread et un autre pour un autre thread.Vous pouvez vérifier l'ID de thread actuel dans le gestionnaire installé, et faire des choses basées dessus. il n'est pas nécessaire de les installer avant de créer les threads, il est plus facile de les installer avant de créer les threads, et il reste beaucoup moins de fenêtres de course.)
pthread_t somethread;
avec somethread
un thread qui est dans un appel système bloquant.
Si vous appelez, de tout fil,
pthread_kill(somethread, SIGUSR1);
le signal SIGUSR1
est envoyé à ce fil.
(Notez que le pthread_kill()
appel retourne immédiatement, et vous ne devez pas présumer que le signal a été livré encore à ce moment-là. Vous avez besoin d'un autre mécanisme si vous voulez une notification de livraison trop. En outre, le signal est délivré premier, le syscall de blocage est interrompue seulement après la livraison, et si le système est sous une charge lourde, il peut y avoir un délai mesurable entre les deux Habituellement pas, je ne l'ai vu millisecondes, mais ne préjugent pas à ce sujet. . Si vous avez besoin d'une notification, ont le syscall interrompu le faire après le remarque a été interrompue.)
la livraison du signal à l'installation 0 La fonctionprovoque l'interruption du syscall de blocage dans le même thread. L'appel échouera, renvoyant soit un nombre court (pour certains types de sockets), soit -1
avec errno == EINTR
.
Si vous utilisiez à la place raise(SIGUSR1)
, le noyau peut choisir n'importe quel thread entre les threads du processus pour gérer le signal. (À l'exception des fils qui ont dit le noyau qu'ils souhaitent « bloquer » le signal via pthread_sigmask()
ou sigprocmask()
, ou si elles ont hérité d'un tel bloc du fil qui a créé ce fil.) Quoi qu'il en soit, si ce fil est dans un syscall blocage , il sera interrompu (en raison de la livraison du signal); s'il fait quelque chose d'autre, le fil est juste "emprunté" pendant un moment, et il n'y a vraiment aucun signe de l'interruption.
Il sont cas où ce mécanisme est utile. En particulier, je l'ai utilisé avec des minuteries délai d'attente (en utilisant timer_create(CLOCK_MONOTONIC, &event, &timer)
et timer_settime()
pour définir l'événement déclencheur initial du délai d'attente, puis par des répétitions à intervalles courts rapides, toutes les quelques millisecondes) lors de l'utilisation des bibliothèques externes avec prise en charge du délai d'attente faible/glitch prises accès. Même une médiocre bibliothèque n'essaiera pas un blocage plus de quelques fois dans le pire des cas, si tous échouent avec une erreur EINTR
- bien sûr, le cas courant, typique, est que le premier force la bibliothèque à rapporter le erreur immédiatement. Ce sont les cas de coin qui me dérangent vraiment; Je veux seulement publier du code robuste qui n'est pas enclin à basculer juste parce que la lune se trouve dans la mauvaise phase.
[problème XY] classique (http://xyproblem.info). Qu'est-ce que vous essayez vraiment de faire? –
Le programme que j'ai joint devrait être expliqué, j'essaie de générer EINTR par raise() – bzzzz7
J'ai reformulé votre question, de sorte qu'elle exprime le problème que vous voulez résoudre. – a3f