Come posso verificare quali segnali sta ascoltando un processo?


81

Come posso verificare se un processo in esecuzione rileva un segnale, lo ignora o lo blocca? Idealmente mi piacerebbe vedere un elenco di segnali, o almeno non è necessario inviare effettivamente il segnale per verificare.

Risposte:


109

Sotto Linux, puoi trovare il PID del tuo processo, quindi guardare /proc/$PID/status. Contiene linee che descrivono quali segnali sono bloccati (SigBlk), ignorati (SigIgn) o catturati (SigCgt).

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

Il numero a destra è una maschera di bit. Se lo converti da esadecimale a binario, ogni 1 bit rappresenta un segnale intercettato, contando da destra a sinistra a partire da 1. Quindi, interpretando la linea SigCgt, possiamo vedere che il mio initprocesso sta rilevando i seguenti segnali:

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

(Ho trovato la mappatura da numero a nome eseguendo kill -lda bash.)

EDIT : E a grande richiesta, una sceneggiatura, in 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
Se un segnale è elencato sotto SigBlk, appare anche in SigCgt? Perché bloccandolo, significa solo che il segnale verrà risentito un po 'più tardi e che è necessario catturarlo?
CMCDragonkai,

No, puoi bloccare un segnale senza essere pronto a catturarlo. Se non si rileva un segnale, si verificherà un'azione predefinita in base al segnale (di solito terminazione del processo). Se vuoi maggiori dettagli, dovresti aprire una domanda.
Jander,

A che serve una versione POSIX di uno script che legge /proc? Funzionerà solo su Linux ... E localnon è POSIX. Beh, è ​​un po ', ma il suo effetto è "non specificato".
Kusalananda

2
@Kusalananda: Linux non implica Bash - ad esempio, le piccole piattaforme integrate usano spesso Busybox - ma la conformità POSIX è una garanzia pressoché moderna /bin/sh. Hai ragione local; Lo pulirò.
Jander

@Jander Fair point. Confesso di fare una frettolosa ipotesi su Bash e Linux.
Kusalananda

23

Su Solaris, eseguire psigl'id di processo per ottenere un elenco di segnali e come verranno gestiti.

Per esempio:

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
[...]

che mostra che SIGHUP, SIGILL, ecc. saranno catturati dalla stessa funzione del gestore del segnale termsig_sighandler, che verrà eseguita senza l'uso di alcun flag che potrebbe essere impostato tramite sigactione tutti i segnali che verranno temporaneamente mascherati mentre il gestore del segnale è in esecuzione (in questo caso tutti quelli che usano lo stesso gestore di segnale, quindi non viene reinserito mentre è già in esecuzione). Puoi anche vedere che SIGQUIT e SIGTERM verranno ignorati, SIGKILL e SIGPWR usano le azioni di segnale predefinite del sistema e SIGCLD specifica il flag RESTART, quindi se il suo gestore di segnale interrompe una chiamata di sistema, la syscall verrà riavviata.


Eccezionale! Speravo che qualcuno avrebbe aggiunto una risposta non Linux.
Jander

4

(Questa risposta è simile alla risposta di @ user18096, in quanto crea uno script attorno alla risposta di @ Jander.)

Ho scritto a psig scriptper prendere un PID (o tutti i PID) e creare output leggibili dall'uomo dalle maschere di segnale in /proc/<PID>/status.

Esempio di output:

% ./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

Avvertenze:

  • Questa è una risposta specifica per Linux.
  • Potrebbe essere necessaria una versione di Python relativamente nuova per eseguire lo script, che utilizza withe OrderedDict.

2

Continuo a tornare alla bella risposta di @ Jander sperando in un decodificatore copia e incolla di fronte a simili:

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

Immagino che dovrò bussare qualcosa ... dì:

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:~$ 

Volevo che fosse un po 'leggibile, ma questo ha reso un po' più goffo invocare di quanto mi piacerebbe, quindi, grazie al suggerimento di @ alanc, lo salverò come ~ / bin / psig.


2

Uso Questo(collegamento interrotto) questa libreria per ottenere informazioni sui lavori in esecuzione.

C'è un campo speciale nel struct Jobper i segnali, chiamatosigCgt

Puoi usare qualcosa del genere:

#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;
}

Mi piacerebbe ma il link non funziona.
Michael Fox,

1
@MichaelFox guarda la mia modifica. L'utente ha cancellato il suo account. Il nuovo link punta allo stesso progetto
LittleByBlue,

1

Su FreeBSD, usa procstat -i <PID>per vedere quali segnali vengono ignorati dal processo. Allo stesso modo, procstat -j <PID>per vedere quali segnali sono bloccati dai thread del processo. Entrambi i comandi mostrano se un segnale è in sospeso.

Uscita campione:

$ 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 -- ...

Vedi procstat (1) .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.