local $SIG et boucles

Le
espie
J'ai un bout de code moyennement elegant.

Disons:

sub foo
{
my $handler = sub { my $sig = shift; print STDERR "Caught SIG$sig";};

local $SIG{INT} = $handler;
local $SIG{QUIT} = $handler;
local $SIG{HUP} = $handler;
local $SIG{KILL} = $handler;
local $SIG{TERM} = $handler;
{
# do something that shouldn't be interrupted
}
}


(Un des cas d'utilisation de local qui reste raisonnable en perl).

J'aimerais bien mettre une boucle plutot que de repeter 5 fois la
meme chose, mais evidemment, ca ne va pas marcher, puisque le local
va etre local a la boucle.

Je pourrais AUSSI sauvegarder les gestionnaires de signaux et les
restaurer en sortie, mais c'est moche.

Je pourrais meme fabriquer le code qui va bien et le confier a un eval
encore plus moche!

Quelqu'un aurait une idee brillante ? est-ce qu'il y a moyen d'avoir
un "local -1" qui affecterait les variables du niveau du dessus de
la portee actuelle ?
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
espie
Le #26521463
Ah si, j'ai une autre technique un peu usine a gaz, emuler local
avec une classe et un DESTROY.
Genre, je pourrais tout mettre dans un objet construit avec un destructeur.
Oui, ca fonctionne.
Moins usine a gaz ?...
#! /usr/bin/perl
package Local;
sub new
{
my $class = shift;
bless {}, $class;
}
sub DESTROY
{
my $self = shift;
while (my ($name, $value) = each %$self) {
$SIG{$name} = $value;
}
}
sub set
{
my ($self, $name, $v) = @_;
$self->{$name} = $SIG{$name};
$SIG{$name} = $v;
}
package main;
sub bar
{
my $n = Local->new;
for my $sig (qw(INT QUIT)) {
$n->set($sig, sub { print STDERR "Caught signal2n"; });
}
kill -INT, $$;
}
sub foo
{
my $n = Local->new;
for my $sig (qw(INT QUIT)) {
$n->set($sig, sub { print STDERR "Caught signaln"; });
}
bar();
kill -INT, $$;
}
foo();
kill -INT, $$;
Benoit Izac
Le #26521471
Bonjour,
Le 13/07/2019 à 10:30, Marc Espie a écrit dans le message
J'ai un bout de code moyennement elegant.
Disons:
sub foo
{
my $handler = sub { my $sig = shift; print STDERR "Caught SIG$sign";};
local $SIG{INT} = $handler;
local $SIG{QUIT} = $handler;
local $SIG{HUP} = $handler;
local $SIG{KILL} = $handler;
local $SIG{TERM} = $handler;
{
# do something that shouldn't be interrupted
}
}
(Un des cas d'utilisation de local qui reste raisonnable en perl).
J'aimerais bien mettre une boucle plutot que de repeter 5 fois la
meme chose, mais evidemment, ca ne va pas marcher, puisque le local
va etre local a la boucle.
Je pourrais AUSSI sauvegarder les gestionnaires de signaux et les
restaurer en sortie, mais c'est moche.
Je pourrais meme fabriquer le code qui va bien et le confier a un eval...
encore plus moche!
Quelqu'un aurait une idee brillante ? est-ce qu'il y a moyen d'avoir
un "local -1" qui affecterait les variables du niveau du dessus de
la portee actuelle ?

Ceci semble fonctionner :
my @sig = qw(INT QUIT HUP KILL TERM);
local @SIG{@sig} = ($handler) x @sig;
--
Benoit Izac
espie
Le #26521526
In article
Ceci semble fonctionner :
my @sig = qw(INT QUIT HUP KILL TERM);
local @SIG{@sig} = ($handler) x @sig;

OH, je connaissais pas le x pour les "list repetitions", c'est
joli.
Paul Gaborit
Le #26522086
À (at) Sat, 13 Jul 2019 08:30:19 +0000 (UTC),
(Marc Espie) écrivait (wrote):
[...]
local $SIG{KILL} = $handler;

[...]
J'arrive un peu après la bataille, juste pour dire que ce $handler ne
risque pas de fonctionner puisque le signal KILL n'est pas captable (pas
plus que STOP).
--
Paul Gaborit - Perl en français -
espie
Le #26522168
In article Paul Gaborit
À (at) Sat, 13 Jul 2019 08:30:19 +0000 (UTC),
(Marc Espie) écrivait (wrote):
[...]
local $SIG{KILL} = $handler;

[...]
J'arrive un peu après la bataille, juste pour dire que ce $handler ne
risque pas de fonctionner puisque le signal KILL n'est pas captable (pas
plus que STOP).

Tout a fait.
Pour ma defense, j'ai des trucs bien standards (capter les signaux usuels,
pour entre autres tuer des fils qui vont a voir du mal si je reviens
pas sur la bonne effective uid... oui bon deja c'est louche)
et des trucs un peu moins (jouer avec __DIE__ et __WARN__ dans certains
cas pour faire une trace en sortie tout en utilisant quand meme eval {}
parfois...) donc j'ai du rajouter KILL un jour parce qu'un truc chelou
se produisait.
Publicité
Poster une réponse
Anonyme