Como posso verificar quais sinais um processo está escutando?

77

Como posso verificar se um processo em execução irá capturar um sinal, ignorá-lo ou bloqueá-lo? Idealmente eu gostaria de ver uma lista de sinais, ou pelo menos não ter que realmente enviar o sinal para checar.

    
por Jander 02.08.2013 / 21:28

6 respostas

102

No Linux, você pode encontrar o PID do seu processo e, em seguida, consultar /proc/$PID/status . Ele contém linhas descrevendo quais sinais são bloqueados (SigBlk), ignorados (SigIgn) ou capturados (SigCgt).

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

O número à direita é uma máscara de bits. Se você convertê-lo de hex para binário, cada 1 bit representa um sinal capturado, contando da direita para a esquerda começando com 1. Então, interpretando a linha SigCgt, podemos ver que o meu processo init está captando os seguintes sinais: / p>

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

(Encontrei o mapeamento de número para nome executando kill -l do bash.)

EDITAR : E por demanda popular, um script, em 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
    
por 02.08.2013 / 21:35
23

No Solaris, execute psig no ID do processo para obter uma lista de sinais e como eles serão tratados.

Por exemplo:

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

que mostra que SIGHUP, SIGILL, etc. serão todos capturados pela mesma função de manipulador de sinal termsig_sighandler , que será executada sem usar nenhum dos sinalizadores que podem ser definidos via sigaction , e todos os sinais que serão temporariamente mascarados enquanto o manipulador de sinais estiver em execução (neste caso, todos os aqueles usando o mesmo manipulador de sinal, por isso não é reinserido enquanto já está em execução). Você também pode ver que SIGQUIT & SIGTERM será ignorado, SIGKILL & O SIGPWR usa as ações de sinal padrão do sistema e SIGCLD especifica o sinalizador RESTART, portanto, se seu manipulador de sinal interromper uma chamada do sistema, o syscall será reiniciado.

    
por 03.08.2013 / 08:23
4

(Esta resposta é semelhante à resposta do @ user18096, na medida em que cria um script em torno da resposta do @Jander.)

Eu escrevi um psig script para obter um PID (ou todos os PIDs) e criar resultados legíveis por humanos a partir do máscaras de sinal em /proc/<PID>/status .

Exemplo de saída:

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

Advertências:

  • Esta é uma resposta específica do Linux.
  • Pode ser necessária uma versão relativamente nova do Python para executar o script, ele usa with e OrderedDict .
por 20.12.2015 / 06:28
2

Eu continuo voltando à bela resposta do @Jander esperando por um decodificador copiar e colar quando confrontado com:

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

Acho que vou ter que bater em alguma coisa ... dizer:

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

Eu queria que fosse um pouco legível, mas isso fez com que fosse um pouco mais complicado invocar do que eu gostaria, então, graças à sugestão do @ alanc, vou salvá-lo como ~ / bin / psig.

    
por 05.11.2015 / 00:50
2

Use este (link quebrado) esta biblioteca para obter informações sobre os trabalhos em execução.

Existe um campo especial no struct Job para os sinais, chamado sigCgt

Você pode usar algo assim:

#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;
}
    
por 25.01.2015 / 20:32
1

No FreeBSD, use procstat -i <PID> para ver quais sinais são ignorados pelo processo. Da mesma forma, procstat -j <PID> para ver quais sinais são bloqueados pelos encadeamentos do processo. Ambos os comandos mostram se um sinal está pendente.

Exemplo de saída:

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

Veja procstat (1) .

    
por 09.02.2017 / 22:17