Comment puis-je vérifier quels signaux un processus écoute?


81

Comment puis-je vérifier si un processus en cours attrape un signal, l'ignore ou le bloque? Idéalement, j'aimerais voir une liste de signaux, ou du moins ne pas avoir à envoyer le signal à vérifier.

Réponses:


109

Sous Linux, vous pouvez trouver le PID de votre processus, puis regarder /proc/$PID/status. Il contient des lignes décrivant les signaux bloqués (SigBlk), ignorés (SigIgn) ou capturés (SigCgt).

# cat /proc/1/status
...
SigBlk: 0000000000000000
SigIgn: fffffffe57f0d8fc
SigCgt: 00000000280b2603
...

Le nombre à droite est un masque de bits. Si vous le convertissez d'hex en binaire, chaque bit représente un signal capturé, en comptant de droite à gauche, en commençant par 1. Ainsi, en interprétant la ligne SigCgt, nous pouvons voir que mon initprocessus capte les signaux suivants:

00000000280b2603 ==> 101000000010110010011000000011
                     | |       | ||  |  ||       |`->  1 = SIGHUP
                     | |       | ||  |  ||       `-->  2 = SIGINT
                     | |       | ||  |  |`----------> 10 = SIGUSR1
                     | |       | ||  |  `-----------> 11 = SIGSEGV
                     | |       | ||  `--------------> 14 = SIGALRM
                     | |       | |`-----------------> 17 = SIGCHLD
                     | |       | `------------------> 18 = SIGCONT
                     | |       `--------------------> 20 = SIGTSTP
                     | `----------------------------> 28 = SIGWINCH
                     `------------------------------> 30 = SIGPWR

(J'ai trouvé le mappage numéro-à-nom en exécutant à kill -lpartir de bash.)

EDIT : Et à la demande générale, un script en POSIX sh.

sigparse () {
    i=0
    # bits="$(printf "16i 2o %X p" "0x$1" | dc)" # variant for busybox
    bits="$(printf "ibase=16; obase=2; %X\n" "0x$1" | bc)"
    while [ -n "$bits" ] ; do
        i="$(expr "$i" + 1)"
        case "$bits" in
            *1) printf " %s(%s)" "$(kill -l "$i")" "$i" ;;
        esac
        bits="${bits%?}"
    done
}

grep "^Sig...:" "/proc/$1/status" | while read a b ; do
        printf "%s%s\n" "$a" "$(sigparse "$b")"
    done # | fmt -t  # uncomment for pretty-printing

2
Si un signal est répertorié sous, SigBlkapparaît-il également dans SigCgt? Parce qu'en le bloquant, cela signifie simplement que le signal sera renvoyé un peu plus tard correctement et que les besoins doivent être capturés?
CMCDragonkai

Non, vous pouvez bloquer un signal sans être prêt à l'attraper. Si vous n'attrapez pas de signal, une action par défaut se produira en fonction du signal (généralement, la fin du processus). Si vous voulez plus de détails, vous devez ouvrir une question.
Jander

A quoi sert une version POSIX d'un script lu /proc? Cela ne fonctionnera que sous Linux ... Et localPOSIX n'est pas. Eh bien, c'est un peu le cas, mais son effet est "non spécifié".
Kusalananda

2
@Kusalananda: Linux n'implique pas Bash - par exemple, les petites plates-formes intégrées utilisent souvent Busybox - mais la conformité POSIX est une quasi-garantie pour tout moderne /bin/sh. Vous avez raison local; Je vais nettoyer ça.
Jander

@ Jander Fair Point. J'avoue faire une hypothèse hâtive concernant Bash et Linux.
Kusalananda

23

Sous Solaris, exécutez psigl'ID de processus pour obtenir une liste des signaux et leur traitement.

Par exemple:

bash-4.2$ psig $$
11088:  bash
HUP     caught  termsig_sighandler  0   HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
INT     caught  sigint_sighandler   0
QUIT    ignored
ILL     caught  termsig_sighandler  0   HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
TRAP    caught  termsig_sighandler  0   HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
ABRT    caught  termsig_sighandler  0   HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
EMT     caught  termsig_sighandler  0   HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
FPE     caught  termsig_sighandler  0   HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
KILL    default
BUS     caught  termsig_sighandler  0   HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
SEGV    caught  termsig_sighandler  0   HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
SYS     caught  termsig_sighandler  0   HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
PIPE    caught  termsig_sighandler  0   HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
ALRM    caught  termsig_sighandler  0   HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
TERM    ignored
USR1    caught  termsig_sighandler  0   HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
USR2    caught  termsig_sighandler  0   HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
CLD     blocked,caught  0x4898e8    RESTART
PWR     default
WINCH   caught  sigwinch_sighandler 0
[...]

ce qui indique que SIGHUP, SIGILL, etc. seront tous capturés par la même fonction de gestionnaire de signal termsig_sighandler, qui sera exécutée sans utiliser aucun des indicateurs pouvant être définis via sigaction, et tous les signaux qui seront temporairement masqués lorsque le gestionnaire de signal est en cours d'exécution (dans ce cas, tous ceux qui utilisent le même gestionnaire de signal, de sorte qu'ils ne sont pas réentrés lorsqu'ils sont déjà en cours d'exécution). Vous pouvez également voir que SIGQUIT & SIGTERM sera ignoré, que SIGKILL & SIGPWR utilise les actions de signal par défaut du système et que SIGCLD spécifie l'indicateur RESTART. Ainsi, si son gestionnaire de signaux interrompt un appel système, l'appel système sera redémarré.


Impressionnant! J'espérais que quelqu'un ajouterait une réponse autre que Linux.
Jander

4

(Cette réponse est similaire à celle de @ user18096, en ce sens qu'elle crée un script autour de la réponse de @ Jander.)

J'ai écrit un psig scriptpour prendre un PID (ou tous les PID) et créer une sortie lisible par l'homme à partir des masques de signaux de /proc/<PID>/status.

Exemple de sortie:

% ./psig -a
[     1] Signals Queued: 8/773737
[     1] Signals Pending:
[     1] Signals Pending (Shared):
[     1] Signals Blocked:
[     1] Signals Ignored: SIGPIPE
[     1] Signals Caught: SIGHUP,SIGINT,SIGABRT,SIGUSR1,SIGSEGV,SIGALRM,SIGTERM,SIGCHLD,SIGPWR
...
[ 31001] Signals Queued: 0/773737
[ 31001] Signals Pending:
[ 31001] Signals Pending (Shared):
[ 31001] Signals Blocked: SIGHUP,SIGINT,SIGQUIT,SIGILL,SIGTRAP,SIGABRT,SIGBUS,SIGFPE,SIGUSR1,SIGUSR2,SIGPIPE,SIGALRM,SIGTERM,SIGSTKFLT,SIGCHLD,SIGCONT,SIGTSTP,SIGTTIN,SIGTTOU,SIGURG,SIGXCPU,SIGXFSZ,SIGPROF,SIGWINCH,SIGIO,SIGPWR,SIGSYS,SIGRTMIN,SIGRTMIN+1,SIGRTMIN+2,SIGRTMIN+3,SIGRTMIN+4,SIGRTMIN+5,SIGRTMIN+6,SIGRTMIN+7,SIGRTMIN+8,SIGRTMIN+9,SIGRTMIN+10,SIGRTMIN+11,SIGRTMIN+12,SIGRTMIN+13,SIGRTMIN+14,SIGRTMIN+15,SIGRTMAX-14,SIGRTMAX-13,SIGRTMAX-12,SIGRTMAX-11,SIGRTMAX-10,SIGRTMAX-9,SIGRTMAX-8,SIGRTMAX-7,SIGRTMAX-6,SIGRTMAX-5,SIGRTMAX-4,SIGRTMAX-3,SIGRTMAX-2,SIGRTMAX-1,SIGRTMAX
[ 31001] Signals Ignored: SIGHUP,SIGINT,SIGQUIT,SIGPIPE,SIGXFSZ
[ 31001] Signals Caught: SIGBUS,SIGUSR1,SIGSEGV,SIGUSR2,SIGALRM,SIGTERM,SIGVTALRM

Mises en garde:

  • Ceci est une réponse spécifique à Linux.
  • Une version relativement nouvelle de Python pourrait être nécessaire pour exécuter le script, elle utilise withet OrderedDict.

2

Je reviens sans cesse sur la jolie réponse de @ Jander dans l'espoir d'un décodeur copier-coller lorsque confronté à un problème similaire à:

user@machine:~$ grep Sig...: /proc/18475/status
SigPnd: 0000000000000000
SigBlk: fffffffe7dfbfaff
SigIgn: 0000000000001000
SigCgt: 0000000182006e47
user@machine:~$ 

Je suppose que je vais devoir casser quelque chose ... dis:

user@machine:~$ ruby -wn - /proc/18475/status <<'EOF'
if $_.match(/Sig(Pnd|Blk|Ign|Cgt):\s([0-9a-f]{16})/) == nil
  next
end
field = $1
mask = $2.to_i(16)
names = []
Signal.list().each_pair() {
  |name, number|
  if number == 0
    # "EXIT" => 0
    next
  end
  if (mask & (1 << (number - 1))) == 0
    next
  end
  names << name
}
puts("Sig#{field}: #{names.join(" | ")}")
EOF
SigPnd: 
SigBlk: HUP | INT | QUIT | ILL | TRAP | IOT | ABRT | FPE | BUS | SYS | PIPE | ALRM | TERM | URG | TSTP | CONT | CHLD | CLD | TTIN | TTOU | IO | XCPU | XFSZ | PROF | WINCH | USR1 | USR2 | PWR | POLL
SigIgn: PIPE
SigCgt: HUP | INT | QUIT | BUS | SEGV | ALRM | TERM | VTALRM | USR1 | USR2
user@machine:~$ 

Je voulais que ce soit un peu lisible, mais cela rendait l'invocation un peu plus maladroite que je ne l'aurais souhaité, alors, grâce à la suggestion de @ alanc, je l'enregistrerai sous le nom ~ / bin / psig.


2

Utilisation cette(lien brisé) cette bibliothèque pour obtenir des informations sur les travaux en cours.

Il y a un champ spécial dans le struct Jobpour les signaux, appelésigCgt

Vous pouvez utiliser quelque chose comme ceci:

#include"read_proc.h"
int main(void)
{
    struct Root * rt=read_proc();
    struct Job * jb=rt->first->job;
    printf("%ull\n",jb->sigCgt);
    return 0;
}

J'adorerais mais le lien est brisé.
Michael Fox

1
@ MichaelFox voir mon édition. L'utilisateur a supprimé son compte. Le nouveau lien pointe vers le même projet
LittleByBlue

1

Sous FreeBSD, utilisez procstat -i <PID>pour voir quels signaux sont ignorés par le processus. De même, procstat -j <PID>pour voir quels signaux sont bloqués par les threads de processus. Les deux commandes indiquent si un signal est en attente.

Exemple de sortie:

$ procstat -i 38540 PID COMM SIG FLAGS 38540 nsulfd HUP -I- 38540 nsulfd INT -I- 38540 nsulfd QUIT -I- 38540 nsulfd ILL --- 38540 nsulfd TRAP --- ...

$ procstat -j 38540 PID TID COMM SIG FLAGS 38540 101220 nsulfd HUP -- 38540 101220 nsulfd INT -- 38540 101220 nsulfd QUIT -B 38540 101220 nsulfd ILL -- 38540 101220 nsulfd TRAP -- ...

Voir procstat (1) .

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.