Как я могу проверить, какие сигналы слушает процесс?

81

Как я могу проверить, будет ли запущенный процесс перехватывать сигнал, или игнорировать его, или блокировать? В идеале я хотел бы видеть список сигналов, или, по крайней мере, не нужно отправлять сигнал для проверки.

Jander
источник

Ответы:

109

В Linux вы можете найти PID вашего процесса, а затем посмотреть /proc/$PID/status. Он содержит строки, описывающие, какие сигналы заблокированы (SigBlk), проигнорированы (SigIgn) или перехвачены (SigCgt).

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

Число справа является битовой маской. Если вы преобразуете его из шестнадцатеричного в двоичный, каждый 1-бит представляет пойманный сигнал, считая справа налево, начиная с 1. Таким образом, интерпретируя строку SigCgt, мы видим, что мой initпроцесс перехватывает следующие сигналы:

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

(Я нашел отображение числа на имя, запустив kill -lbash.)

РЕДАКТИРОВАТЬ : И по многочисленным просьбам, сценарий, в 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
источник
2
Если сигнал указан в списке SigBlk, он также отображается в SigCgt? Потому что, блокируя его, это просто означает, что сигнал будет повторно послан чуть позже, и нужно его поймать?
CMCDragonkai
Нет, вы можете заблокировать сигнал, не будучи готовым его поймать. Если вы не улавливаете сигнал, в зависимости от сигнала будет выполняться действие по умолчанию (обычно завершение процесса). Если вы хотите больше подробностей, вы должны открыть вопрос.
Декабрь
Какая польза от чтения POSIX-версии скрипта /proc? Это будет работать только на Linux ... И localне POSIX. Ну, это вроде как, но его эффект "не определен".
Кусалананда
2
@Kusalananda: Linux не подразумевает Bash - например, небольшие встроенные платформы часто используют Busybox - но соответствие POSIX является почти гарантией для любого современного /bin/sh. Вы правы насчет local; Я уберу это.
Jander
@ Jander Честная точка зрения. Признаюсь, что сделал поспешное предположение относительно Bash и Linux.
Кусалананда
23

В Solaris запустите psigидентификатор процесса, чтобы получить список сигналов и способы их обработки.

Например:

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

который показывает, что SIGHUP, SIGILL и т. д. будут пойманы одной и той же функцией обработчика сигнала termsig_sighandler, которая будет выполняться без использования каких-либо флагов, которые могут быть установлены с помощью sigaction, и всех сигналов, которые будут временно маскироваться, пока обработчик сигнала выполняется (в этом случае все используют один и тот же обработчик сигнала, поэтому он не будет повторно введен во время работы). Вы также можете видеть, что SIGQUIT & SIGTERM будут игнорироваться, SIGKILL и SIGPWR используют системные действия по умолчанию для сигналов, а SIGCLD задает флаг RESTART, поэтому, если его обработчик сигналов прерывает системный вызов, системный вызов будет перезапущен.

alanc
источник
Потрясающие! Я надеялся, что кто-нибудь добавит ответ не из Linux.
Jander
4

(Этот ответ похож на ответ @ user18096 в том смысле, что он создает сценарий вокруг ответа @ Jander.)

Я написал, psig scriptчтобы взять PID (или все PID) и создать читабельный вывод из масок сигналов /proc/<PID>/status.

Пример вывода:

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

Предостережения:

  • Это является конкретным ответом Linux.
  • Может потребоваться относительно новая версия Python для запуска скрипта, он использует withи OrderedDict.
erik.weathers
источник
2

Я продолжаю возвращаться к красивому ответу @ Jander, надеясь на декодер копирования и вставки, когда сталкиваюсь с подобным:

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

Думаю, мне придется что-то сбить с ног ... сказать:

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

Я хотел, чтобы он был несколько разборчивым, но это делало его немного неуклюжим, чтобы вызывать его, поэтому, благодаря предложению @ alanc, я сохраню его как ~ / bin / psig.

Мартин Дори
источник
2

использование это(ссылка не работает) эта библиотека для получения информации о выполняющихся заданиях.

Существует специальное поле struct Jobдля сигналов, называемоеsigCgt

Вы можете использовать что-то вроде этого:

#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
источник
Я бы с удовольствием, но связь не работает.
Майкл Фокс
1
@MichaelFox см. Мое редактирование. Пользователь удалил свою учетную запись. Новая ссылка указывает на тот же проект
LittleByBlue
1

В FreeBSD используйте, procstat -i <PID>чтобы увидеть, какие сигналы игнорируются процессом. Точно так же, procstat -j <PID>чтобы увидеть, какие сигналы заблокированы потоками процесса. Обе команды показывают, ожидает ли сигнал.

Образец вывода:

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

Смотрите procstat (1) .

Дипак
источник