Wie kann ich überprüfen, welche Signale ein Prozess abhört?

81

Wie kann ich überprüfen, ob ein laufender Prozess ein Signal erfasst, ignoriert oder blockiert? Im Idealfall möchte ich eine Liste von Signalen sehen oder muss das Signal zumindest nicht wirklich senden, um es zu überprüfen.

Jander
quelle

Antworten:

109

Unter Linux können Sie die PID Ihres Prozesses finden und dann anschauen /proc/$PID/status. Es enthält Zeilen, die beschreiben, welche Signale blockiert (SigBlk), ignoriert (SigIgn) oder abgefangen (SigCgt) werden.

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

Die Zahl rechts ist eine Bitmaske. Wenn Sie es von hexadezimal in binär konvertieren, stellt jedes 1-Bit ein abgefangenes Signal dar und zählt von rechts nach links, beginnend mit 1. Wenn Sie also die SigCgt-Zeile interpretieren, können Sie sehen, dass mein initProzess die folgenden Signale erfasst :

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

(Ich fand die Zuordnung von Nummer zu Name, indem ich kill -lvon der Bash aus lief.)

EDIT : Und auf vielfachen Wunsch ein Skript, 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
Jander
quelle
2
Wenn ein Signal unter aufgeführt ist, SigBlkerscheint es auch in SigCgt? Denn wenn Sie es blockieren, bedeutet dies nur, dass das Signal ein wenig später erneut gesendet wird, und dass das Signal abgefangen werden muss.
CMCDragonkai
Nein, Sie können ein Signal blockieren, ohne bereit zu sein, es abzufangen. Wenn Sie kein Signal empfangen, wird abhängig vom Signal eine Standardaktion ausgeführt (normalerweise Prozessbeendigung). Wenn Sie mehr Details wünschen, sollten Sie eine Frage öffnen.
Jander,
Was nützt eine POSIX-Version eines Skripts, aus dem gelesen wird /proc? Es wird nur unter Linux funktionieren ... und localnicht unter POSIX. Nun, es ist ein bisschen, aber seine Wirkung ist "nicht spezifiziert".
Kusalananda
2
@Kusalananda: Linux impliziert nicht Bash - zum Beispiel verwenden kleine Embedded-Plattformen häufig Busybox - aber POSIX-Konformität ist eine Garantie für alle modernen Betriebssysteme /bin/sh. Da hast du recht local. Ich werde das aufräumen.
Jander
@ Jander Fair point. Ich gebe zu, eine voreilige Annahme in Bezug auf Bash und Linux gemacht zu haben.
Kusalananda
23

Führen Sie unter Solaris psigdie Prozess-ID aus, um eine Liste der Signale und deren Behandlung abzurufen.

Zum Beispiel:

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

Dies zeigt, dass SIGHUP, SIGILL usw. alle von derselben Signalhandlerfunktion abgefangen werden termsig_sighandler, die ausgeführt wird, ohne eines der Flags zu verwenden, die über gesetzt werden könnten sigaction, und alle Signale, die vorübergehend maskiert werden, während der Signalhandler aktiv ist wird ausgeführt (in diesem Fall verwenden alle den gleichen Signalhandler, sodass er nicht erneut eingegeben wird, wenn er bereits ausgeführt wird). Sie können auch sehen, dass SIGQUIT & SIGTERM ignoriert wird, SIGKILL & SIGPWR die Standard-Signalaktionen des Systems verwendet und SIGCLD das RESTART-Flag angibt. Wenn der Signalhandler einen Systemaufruf unterbricht, wird der Syscall neu gestartet.

alanc
quelle
Genial! Ich hatte gehofft, jemand würde eine Nicht-Linux-Antwort hinzufügen.
Jander
4

(Diese Antwort ähnelt der Antwort von @ user18096, da ein Skript um die Antwort von @ Jander erstellt wird.)

Ich habe ein geschrieben psig script, um eine PID (oder alle PIDs) zu nehmen und eine für Menschen lesbare Ausgabe von den Signalmasken in zu erstellen /proc/<PID>/status.

Beispielausgabe:

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

Vorsichtsmaßnahmen:

  • Dies ist eine Linux-spezifische Antwort.
  • Benötigt möglicherweise eine relativ neue Python-Version, um das Skript auszuführen, das withund verwendet OrderedDict.
erik.weathers
quelle
2

Ich komme immer wieder auf @ Janders hübsche Antwort zurück und hoffe auf einen Copy-and-Paste-Decoder, wenn ich mit Folgendem konfrontiert werde:

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

Ich schätze, ich muss etwas kaputtmachen ... sagen:

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

Ich wollte, dass es etwas leserlich ist, aber das macht es etwas umständlicher, es aufzurufen, als ich es gerne hätte. Dank @alancs Vorschlag werde ich es also als ~ / bin / psig speichern.

Martin Dorey
quelle
2

Verwenden diese(link broken) diese Bibliothek, um Informationen über die laufenden Jobs zu erhalten.

Es gibt ein spezielles Feld struct Jobfür die Signale, genanntsigCgt

Sie können so etwas verwenden:

#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;
}
LittleByBlue
quelle
Ich würde gerne, aber die Verbindung ist unterbrochen.
Michael Fox
1
@MichaelFox siehe meine bearbeiten. Der Benutzer hat seinen Account gelöscht. Der neue Link verweist auf dasselbe Projekt
LittleByBlue
1

Unter FreeBSD können Sie procstat -i <PID>sehen, welche Signale vom Prozess ignoriert werden. Auf ähnliche Weise können Sie feststellen, procstat -j <PID>welche Signale von den Prozessthreads blockiert werden. Beide Befehle zeigen an, ob ein Signal ansteht.

Beispielausgabe:

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

Siehe procstat (1) .

Deepak
quelle