Enviando um sinal para um processo pai

1

Estou tentando implementar um tempo limite para um script grande que chama muito o processo externo.

Eu inicio um processo separado como um cão de guarda que verifica cada segundo se o tempo limite for atingido

(

  PARENT_PID=$$

  ((t = 2 ))
  while ((t > 0)); do
    sleep 1
    ((t -= 1))
  done

  kill -s ALRM ${PARENT_PID} 2> /dev/null

) &

E então eu interceptar o sinal ALRM no script principal

trap critical ALRM

e finalmente na função crítica eu imprimo algum texto e saio do programa de forma limpa

Agora o problema

  • se o tempo limite ocorrer enquanto $ PARENT_PID estiver em execução, tudo funcionará como esperado
  • se o tempo limite ocorrer enquanto um processo filho está em execução (por exemplo, eu chamo o openssl e o openssl está em execução), nada acontece. Se eu terminar o processo filho em execução (por exemplo, pressionando CRTL + C ), o trap do processo pai será ativado e tudo continuará como esperado

Como posso resolver o problema? Para que a armadilha no processo pai seja chamada e eu possa terminar o todo?

Atualizar

Se o watchdog mata com -KILL o processo pai, o processo com toda a criança processada é encerrado como esperado

O problema é que eu gostaria de interceptar o tempo limite e gerar alguma saída. Por esse motivo eu uso o sinal ALRM.

O sinal KILL não pode ser ignorado enquanto o ALRM pode.

Minha ideia no momento é a seguinte:

  • o processo pai tem uma armadilha para o alarme
  • o processo filho ignora o sinal de alarme
  • quando o sinal é enviado ao pai, o processo filho está em execução e o pai está em segundo plano
  • meu processo é acordado quando o filho é encerrado

Se isso estiver correto, minha ideia nunca funcionará.

Para que funcione, eu devo para cada processo filho

  • inicie em segundo plano
  • aguarde e continue

Para que o processo pai seja capaz de capturar o sinal

Estou correto?

Atualização 2

Um exemplo reduzido

critical() {
    printf "whathever\n"
    WATCHDOG_PID=$!
    kill -TERM $WATCHDOG_PID
}

(

    PARENT_PID=$$

    ((t = "${TIMEOUT}" ))
    while ((t > 0)); do
        sleep 1
        ((t -= 1))
    done

    kill -s ALRM ${PARENT_PID} 2> /dev/null

) &

trap critical ALRM

# an example of a long running command
(echo 'Q' | openssl s_client -connect corti.li:imap -servername corti.li -verify 6 ) &
wait

WATCHDOG_PID=$!
kill -TERM $WATCHDOG_PID

Se o sinal ALRM for enviado enquanto openssl estiver em execução, nada acontece. Mesmo se o openssl estiver no fundo, o trap nunca é chamado

    
por Matteo 18.08.2017 / 15:39

1 resposta

1

Uma resposta completa precisa do código do seu pai, mas falta isso, aqui está uma sugestão do que provavelmente está acontecendo:

Especificações básicas do grupo aberto Edição 6 - Seção 2.11

When a signal for which a trap has been set is received while the shell is waiting for the completion of a utility executing a foreground command, the trap associated with that signal shall not be executed until after the foreground command has completed.

When the shell is waiting, by means of the wait utility, for asynchronous commands to complete, the reception of a signal for which a trap has been set shall cause the wait utility to return immediately with an exit status >128, immediately after which the trap associated with that signal shall be taken.

(formatando o meu)

O que isto significa é que, se o seu pai está esperando com qualquer coisa, exceto o comando wait , o manuseio do sinal é atrasado até o final do que está fazendo.

Cabe a você fazer com que seus pais esperem com wait , para que ele possa receber seu SIGALRM imediatamente.

    
por 18.08.2017 / 16:37