2012-07-23 4 views
5

Desidero specificare un gestore di segnale in Perl, ma utilizzando il numero, non il nome. È possibile in un modo succinto? In particolare, la mancanza di simmetria con l'uccisione sporge. Ad esempio, invece diSpecificare il gestore del segnale Perl utilizzando il numero, non il nome

$SIG{USR2} = \&myhandler; 

Mi piacerebbe dire

$SIG{12} = \&myhandler; 

il migliore che ho in questo momento è quello di "utilizzare Config" e frugare in $ Config {} sig_name, sulla base di il codice in perldoc perldc. Questo è prolisso e sembra inutilmente complicato.

Motivazione: l'ho desiderato in due casi di recente.

1: Sono stato avviato da un processo genitore buggato che imposta erroneamente segnali che mi interessa ignorare, e voglio solo ripristinare tutto al valore predefinito. ad esempio http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=679630 L'obiettivo sarebbe qualcosa forza semplice e bruta come:

foreach my $i (1..32) { $SIG{$i} = 'DEFAULT'; } 

2: Sto scrivendo un, come invisibile-come-possibile script wrapper sottile. Se il programma che sto avvolgendo esce con un segnale, voglio uscire con quello stesso segnale. Tuttavia, catturo alcuni segnali, quindi ho bisogno di cancellare il mio gestore di segnale per assicurarmi che effettivamente esca invece di entrare nel mio gestore di segnale. Il mio obiettivo è quello di scrivere qualcosa di breve come questo:

$ret = system("./other-program"); 
$SIG{$ret & 127} = 'DEFAULT'; 
kill $ret & 127, $$; 

risposta

2

Prima domanda:

use Config qw(%Config); 

my @sig_name_by_num; 
@sig_name_by_num[ split(' ', $Config{sig_num}) ] = split(' ', $Config{sig_name}); 

$SIG{$sig_name_by_num[12]} = \&handler; 

Seconda domanda:

use Config qw(%Config); 

$SIG{$_} = 'DEFAULT' for split ' ', $Config{sig_name}; 

oppure

$SIG{$_} = 'DEFAULT' for keys %SIG; 

oppure

$_ = 'DEFAULT' for values %SIG; 

Terza domanda

use Config qw(%Config); 

my @sig_name_by_num; 
@sig_name_by_num[ split(' ', $Config{sig_num}) ] = split(' ', $Config{sig_name}); 

my $sig_num = $? & 0x7F; 
$SIG{$sig_name_by_num[$sig_num]} = 'DEFAULT'; 
kill($sig_num => $$); 
2

Se si desidera solo per impostare tutti i segnali in una sola volta, non è necessario conoscere i loro numeri:

$SIG{$_} = 'DEFAULT' for keys %SIG; 

Utilizzando $Config{sig_name}/$Config{sig_num} è l'unico portatile per mappare i numeri di segnale a nomi, ma un modo rapido e sporco che funziona su molti sistemi Unix-y è

$sig_name = qx(kill -l $sig_num); 

($sig_name dovrà poi un fine riga, così in pra ctice che ci si vuole fare qualcosa di simile

chomp($sig_name = qx(kill -l $sig_num)); 
($sig_name) = qx(kill -l $sig_num) =~ /(\S+)/; 

)

Questo non è necessariamente più conciso rispetto all'utilizzo %Config, però, a meno che lo ha trasformato in una funzione.

sub sig_no { chomp(my ($sig_no = qx(kill -l $_[0])); $sig_no } 

$SIG{ sig_no($ret & 127) } = 'DEFAULT'; 
... 
+0

Sono dubbia della tecnica "chiavi% SIG". Un Perl (5.12.4) abbastanza recente consiglia di andare a $ Config {sig_name}, e credo che sia perché storicamente non si poteva contare su Perl per popolare% SIG con segnali che non erano stati impostati personalmente. Sembra in pratica che 5.12.4 su Linux riempia le chiavi, ma non è chiaro che sia portatile su sistemi o versioni di Perl. –