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 heade il processo in esecuzione si sorttrovano 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 timeoutprogramma 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, timeoutpassa 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 timeoutdirettamente dalla riga di comando e si preme Ctrl+ C, il SIGINT risultante viene ricevuto sia dal timeoutprocesso figlio che dal processo figlio, ma non dalla shell interattiva che è timeoutil processo padre. Quando timeoutviene chiamato da uno script, solo la shell che esegue lo script riceve il segnale: timeoutnon lo riceve poiché si trova in un diverso gruppo di processi.
È possibile impostare un gestore di segnale in uno script di shell con trapincorporato. 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 killper inoltrare il segnale al timeoutgruppo di processo.
#!/bin/sh
trap 'kill -INT -$pid' INT
timeout 5 sleep 10 &
pid=$!
wait $pid
bgdifgcomandi. Ad ogni modo, c'è una differenza tra i tuoi esempi 1 ° e 3d?