2010-07-14 1 views
7

Che sta succedendo qui? Pensavo che SIGINT sarebbe stata inviata al gruppo di processi in primo piano.Perché SIGINT non viene catturato qui?

(penso, forse, che il sistema() è in esecuzione un guscio che sta creando un nuovo gruppo di processo per il processo figlio? Qualcuno può confermare?)

% perl 
local $SIG{INT} = sub { print "caught signal\n"; }; 
system('sleep', '10'); 

Poi premere Ctrl + D poi Ctrl + c immediatamente e notare che il "segnale catturato" non viene mai stampato.

Mi sento come se fosse una cosa semplice ... ad ogni modo per aggirare questo problema? Il problema è che quando si esegue un gruppo di comandi tramite il sistema si ottiene tenendo premuto ctrl + c fino a quando tutte le iterazioni sono completate (perché perl non ottiene mai SIGINT) ed è piuttosto fastidioso ...

Come può essere risolto? (Ho già provato utilizzando fork() direttamente e capire che questo funziona ... questa non è una soluzione accettabile in questo momento)

UPDATE: si prega di notare, questo non ha nulla a che fare con "il sonno", solo il fatto che il comando impiega una quantità arbitraria di tempo per l'esecuzione che è considerevolmente maggiore di quella del perl attorno ad esso. Tanto che premendo ctrl + c viene inviato al comando (come nel gruppo di processi in primo piano?) E in qualche modo non viene mai inviato a perl.

risposta

4

da perldoc system:

Dal SIGINT e SIGQUIT vengono ignorati durante l'esecuzione del sistema, se vi aspettate il vostro programma per terminare alla ricezione di questi segnali è necessario disporre di farlo da sé in base alla valore di ritorno.

@args = ("command", "arg1", "arg2"); 
system(@args) == 0 
    or die "system @args failed: $?" 

Se vuoi ispezionare manualmente il fallimento del sistema, è possibile controllare tutte le possibili guasti modalità di ispezione $? in questo modo:

if ($? == -1) { 
    print "failed to execute: $!\n"; 
} 
elsif ($? & 127) { 
    printf "child died with signal %d, %s coredump\n", 
     ($? & 127), ($? & 128) ? 'with' : 'without'; 
} 
else { 
    printf "child exited with value %d\n", $? >> 8; 
} 

alternativa, è possibile controllare il valore di $ {^ CHILD_ERROR_NATIVE} con la W *() chiama dal modulo POSIX

+3

ho bisogno di leggere la documentazione da capo: -/Grazie. – dlamotte

+1

Aggiungo che il motivo per cui è necessario ispezionare il valore di ritorno del bambino è che la shell fornisce il^c/INT all'intero gruppo di processi, a perl e ai bambini, in questo caso terminando il figlio 'sleep 10'. Se semplicemente 'kill -INT $ perl_pid' da un'altra shell, perl sarà felice di chiamarti SIG_IGNore. – pilcrow

0

non ho ben capito cosa si sta cercando di ottenere qui ... ma hai provato semplicemente a confronto a:

perl -wle'local $SIG{INT} = sub { print "caught signal"; }; sleep 10;' 

può spiegare l'effetto che si sta cercando di andare per, e perché stai invocando la shell? Puoi semplicemente chiamare direttamente nel programma esterno senza coinvolgere la shell?

+0

vedere la mia sezione UPDATE, "dormienti" non ha nulla a che fare con esso ... è semplicemente un segnaposto per un processo arbitrario. Potrebbe facilmente essere cambiato con "grep something" che si bloccherà per sempre visto che si aspetta di leggere i dati dallo stdin – dlamotte

+0

@xyld: Mi rendo conto che il sonno è un segnaposto. Stavo chiedendo perché avevi bisogno di invocare la shell, invece di chiamare direttamente il tuo processo. – Ether

+0

Non lo sono esplicitamente, ma l'interprete perl potrebbe farlo come parte di "system()". – dlamotte