gratifiant > comp.lang.* > comp.lang.perl

Marc Espie (13/07/2019, 10h30)
J'ai un bout de code moyennement elegant.

Disons:

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

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 ?
Marc Espie (13/07/2019, 12h15)
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 signal2\n"; });
}

kill -INT, $$;
}

sub foo
{
my $n = Local->new;
for my $sig (qw(INT QUIT)) {
$n->set($sig, sub { print STDERR "Caught signal\n"; });
}

bar();
kill -INT, $$;
}

foo();
kill -INT, $$;
Benoit Izac (13/07/2019, 13h32)
Bonjour,

Le 13/07/2019 à 10:30, Marc Espie a écrit dans le message
<qgc4qr$1vpq$1> :

[..]
> 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;
Marc Espie (14/07/2019, 09h31)
In article <87o91ykw50.fsf>, Benoit Izac <benoit.izac> wrote:
>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 (22/07/2019, 00h23)
À (at) Sat, 13 Jul 2019 08:30:19 +0000 (UTC),
espie (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).
Marc Espie (23/07/2019, 20h18)
In article <874l3ff2mp.fsf>,
Paul Gaborit <Paul.Gaborit+news> wrote:
>À (at) Sat, 13 Jul 2019 08:30:19 +0000 (UTC),
>espie (Marc Espie) écrivait (wrote):
>[...]
>[...]
>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.
Discussions similaires