
Outil d'observabilité en direct des signaux du noyau utilisant des points de trace eBPF pour diffuser en continu chaque signal levé sur un hôte Linux, montrant en temps réel l'expéditeur, la cible, la disposition, la latence du gestionnaire et les interruptions d'appels système.
sigwire
tail -fpour les signaux. Chaque signal que tout processus sur la machine lève — qui l'a envoyé, qui l'a reçu, quel signal, comment il a été levé (kill(2), le noyau, un timer POSIX), si la cible l'a intercepté et combien de temps son gestionnaire a tourné, s'il a arraché un appel système bloqué avecEINTR— décodé depuis les tracepoints de signaux du noyau et diffusé en direct sur votre terminal. Pas destrace -fsur un seul pid, pas deptrace, aucune coopération des processus concernés.
sigwire transforme les mécanismes de signaux du noyau en un panneau de brassage en direct : chaque ligne est sender ──SIGNAL──▶ target, colorée par sévérité, étiquetée avec comment il a été levé, si la cible l'a intercepté (et combien de temps son gestionnaire a tourné), si elle a interrompu un appel système bloqué (↯ EINTR read), réduit à ×N quand quelque chose spamme, et marqué ☠ quand c'est un coup fatal. Un rail latéral totalise ce qui circule sur le fil ; pausez et sélectionnez une ligne pour inspecter l'image complète — disposition, adresse du gestionnaire, drapeaux sigaction, et les signaux que la cible bloquait à cet instant.
Parce qu'il accroche les tracepoints du noyau, et non un seul processus, une seule exécution surveille tous les signaux sur la machine d'un coup — votre application, un superviseur, le propre mécanisme de défauts du noyau — sans qu'aucun d'eux sache qu'il est tracé.
[!TIP] Deux faces de chaque signal. sigwire surveille à la fois
signal:signal_generate(la vue de l'expéditeur — qui a levé quoi, la ligne du central) etsignal:signal_deliver(la vue de la cible — l'a-t-elle intercepté, avec quel gestionnaire et quels drapeaux, que bloquait-elle, et a-t-elle interrompu un appel système). Deux autres hooks —rt_sigreturn(2)et le tracepoint de sortie d'appel système — chronométrent le gestionnaire et attrapent EINTR. Tout est corrélé en une seule ligne. Cette division est aussi pourquoi le compteur☠ fatalest délibérément conservateur (voir Ce qui compte comme fatal) : la génération a lieu avant la livraison, donc le côté expéditeur ne peut pas connaître le sort d'un signal — seul le côté livraison le peut, et seulement pour les cas qu'il observe.
curl -fsSL https://yeet.cx | sh # install the yeet daemon (one time) yeet run github:yeet-src/sigwire # run the dashboard (the daemon does the privileged BPF load)
[Guide d'installation manuelle](https://yeet.cx/docs/manual-installation) | Linux uniquement
Rien à configurer : les signaux sont un trafic de fond constant sur n'importe quelle machine, donc les lignes commencent à apparaître immédiatement en haut. Vous voulez en générer vous-même ? `kill -USR1 <pid>`, `Ctrl-C` une tâche en premier plan, ou démarrez un environnement d'exécution géré et observez son GC/ordonnanceur envoyer des signaux à ses propres threads (`↯ EINTR futx` qui défile).
## Contrôles
Le flux suit par défaut le signal le plus récent ; sélectionnez une ligne ou mettez en pause pour le figer pendant que les données continuent de s'accumuler en dessous.
| touche | action |
| ------ | ------ |
| `p` · `Espace` | mettre en pause / reprendre le flux (le figer pour lire) |
| `↑`/`↓`, `k`/`j` | mettre en pause et inspecter une ligne — ouvre le panneau de détails |
| `/` | filtre flou — correspond au processus, pid, signal, source et disposition ; les caractères correspondants sont mis en évidence en direct |
| `e` | filtrer pour **uniquement les appels système interrompus** (`↯ EINTR` / `↺ redémarré`) |
| `s` | ouvrir le **sélecteur de signaux** — masquer ou afficher n'importe quel signal, en direct |
| `Échap` | revenir d'un niveau — effacer le filtre / fermer le sélecteur / abandonner la sélection, puis quitter |
| `q` | quitter |
## Ce que vous regardez
Chaque ligne représente un signal généré, le plus récent en haut :```
WHEN SENDER SIGNAL TARGET NOTE
now bash·4402──SIGINT───▶ node·8813 kill(2) ↯ EINTR read caught 41µs
1.2s systemd·1──────SIGTERM──▶ nginx·1291 kill(2) caught 1.2ms
3.4s kernel·8813──SIGSEGV──▶ chrome·8813 fault default ☠
4.1s postgres·507──SIGUSR1───▶ postgres·509 ×6 kill(2) caught 9µs
Chaque ligne est un bloc : les expéditeur → cible sont comm·pid (l'expéditeur est celui qui a déclenché le signal, current ; la cible est celle à qui il est destiné), le fil au milieu porte le nom du signal coloré par sévérité, ×N regroupe une rafale du signal identique en une seule ligne, et la note à droite donne la source, puis toute interruption d'appel système, puis la disposition.
Chaque ligne est figée au moment où sa distribution se résout et ne mute plus jamais — ainsi une rafale défile comme un journal stable, non pas un agrégat clignotant.
Le fil est coloré par sévérité sur la même palette de 256 couleurs que le reste de l'interface :
| sévérité | signaux | couleur |
|---|---|---|
| tuer | SIGKILL | rouge vif |
| fatal (avec vidage mémoire) | SEGV BUS ABRT ILL FPE TRAP SYS QUIT | rouge |
| terminaison | TERM INT HUP PIPE ALRM … | ambre |
| contrôle de tâches | STOP TSTP TTIN TTOU | jaune |
| continuer | CONT | vert |
| utilisateur | USR1 USR2 | cyan |
| temps réel | SIGRTMIN+n | violet |
| ménage | CHLD URG WINCH … | gris |
La note est la source (kill(2), tgkill, sigqueue, timer, kernel, fault) ; ensuite, si elle a interrompu un appel système bloqué, ↯ EINTR read (ou ↺ restarted read lorsque SA_RESTART l'a automatiquement repris) ; puis la disposition — caught 41µs (un gestionnaire s'est exécuté et combien de temps cela a pris), default (pas de gestionnaire, l'action par défaut a été appliquée), ou ⊘ ignored. Un ☠ marque un coup fatal réel (voir Ce qui compte comme fatal).
[!NOTE]
↯ EINTRest celui à surveiller. Un signal qui arrive alors qu'un thread est bloqué dans un appel système lent (read,poll,accept,futex,nanosleep, …) l'en arrache : l'appel système renvoie-1/EINTRet, à moins que le gestionnaire n'ait définiSA_RESTART, il ne reprend pas — l'application doit réessayer. Oublier cela est un bug classique, exaspérant, dépendant du timing (« pourquoi monread()a-t-il échoué une fois ? »). sigwire le montre en temps réel, et quel appel système a subi le coup. Appuyez surepour masquer tout le reste et ne regarder que les interruptions.
Le rail à droite est la vue agrégée : meilleurs signaux par volume, une répartition par source, et un bilan de distribution — combien de signaux ont été captés vs. ont atteint leur défaut vs. ignorés.