Tasti di segnale come Ctrl+ Cinviano un segnale a tutti i processi nel gruppo di processi in primo piano .
Nel caso tipico, un gruppo di processi è una pipeline. Ad esempio, in head <somefile | sort
, il processo in esecuzione head
e il processo in esecuzione si sort
trovano nello stesso gruppo di processi, così come la shell, quindi ricevono tutti il segnale. Quando si esegue un lavoro in background ( somecommand &
), quel lavoro si trova nel suo gruppo di processi, quindi premendo Ctrl+ Cnon lo influenza.
Il timeout
programma si colloca nel proprio gruppo di processi. Dal codice sorgente:
/* Ensure we're in our own group so all subprocesses can be killed.
Note we don't just put the child in a separate group as
then we would need to worry about foreground and background groups
and propagating signals between them. */
setpgid (0, 0);
Quando si verifica un timeout, timeout
passa attraverso il semplice espediente di uccidere il gruppo di processi di cui è membro. Dal momento che si è inserito in un gruppo di processi separato, il suo processo padre non sarà nel gruppo. L'uso di un gruppo di processi qui garantisce che se l'applicazione figlio esegue il fork in più processi, tutti i suoi processi riceveranno il segnale.
Quando si esegue timeout
direttamente dalla riga di comando e si preme Ctrl+ C, il SIGINT risultante viene ricevuto sia dal timeout
processo figlio che dal processo figlio, ma non dalla shell interattiva che è timeout
il processo padre. Quando timeout
viene chiamato da uno script, solo la shell che esegue lo script riceve il segnale: timeout
non lo riceve poiché si trova in un diverso gruppo di processi.
È possibile impostare un gestore di segnale in uno script di shell con trap
incorporato. Sfortunatamente, non è così semplice. Considera questo:
#!/bin/sh
trap 'echo Interrupted at $(date)' INT
date
timeout 5 sleep 10
date
Se si preme Ctrl+ Cdopo 2 secondi, restano comunque in attesa tutti i 5 secondi, quindi si stampa il messaggio "Interrotto". Questo perché la shell si astiene dall'eseguire il codice trap mentre è attivo un lavoro in primo piano.
Per ovviare a questo, eseguire il processo in background. Nel gestore del segnale, chiamare kill
per inoltrare il segnale al timeout
gruppo di processo.
#!/bin/sh
trap 'kill -INT -$pid' INT
timeout 5 sleep 10 &
pid=$!
wait $pid
bg
difg
comandi. Ad ogni modo, c'è una differenza tra i tuoi esempi 1 ° e 3d?