Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

probleme de debugger

8 réponses
Avatar
espie
J'ai un bout de code qui recupere les exceptions a coup de
eval {....die ...};
if ($@) {
...
die ... # rethrow
}

probleme: comment debugguer tout ca ?

j'aimerais bien que perl -d me montre une stack trace a l'endroit du
premier die...

8 réponses

Avatar
Paul Gaborit
À (at) Tue, 27 Oct 2009 12:01:49 +0000 (UTC),
(Marc Espie) écrivait (wrote):
J'ai un bout de code qui recupere les exceptions a coup de
eval {....die ...};
if ($@) {
...
die ... # rethrow
}

probleme: comment debugguer tout ca ?

j'aimerais bien que perl -d me montre une stack trace a l'endroit du
premier die...



Il est encore possible d'utiliser $SIG{__DIE__} pour capter 'die'
(cf. perlvar) même si la documentation dit qu'un jour cette
possibilité n'existera plus dans les 'eval'.

Mais je ne comprends pas le besoin... Pourquoi ne pas instrumenter
l'appel à 'die' lui-même en lui passant une référence comme argument
(cf. perldoc -f die) ? Dans cette référence on peut stocker toute
l'information nécessaire...

--
Paul Gaborit - <http://perso.mines-albi.fr/~gaborit/>
Perl en français - <http://perl.mines-albi.fr/>
Avatar
espie
In article ,
Paul Gaborit <Paul.Gaborit+ wrote:

À (at) Tue, 27 Oct 2009 12:01:49 +0000 (UTC),
(Marc Espie) écrivait (wrote):
J'ai un bout de code qui recupere les exceptions a coup de
eval {....die ...};
if ($@) {
...
die ... # rethrow
}

probleme: comment debugguer tout ca ?

j'aimerais bien que perl -d me montre une stack trace a l'endroit du
premier die...



Il est encore possible d'utiliser $SIG{__DIE__} pour capter 'die'
(cf. perlvar) même si la documentation dit qu'un jour cette
possibilité n'existera plus dans les 'eval'.

Mais je ne comprends pas le besoin... Pourquoi ne pas instrumenter
l'appel à 'die' lui-même en lui passant une référence comme argument
(cf. perldoc -f die) ? Dans cette référence on peut stocker toute
l'information nécessaire...



En fait, j'ai ete un peu vite en description... ce qui m'interesse, c'est
un cas ou ce n'est pas moi qui suis a l'origine du die. En l'occurrence,
un $object->method avec $object qui vaut undef...

Et perl -d me donne un backtrace... du 2e die. Et j'aimerais non pas capter
die, mais pouvoir dire "si debugguer, alors tu me fais un backtrace dans
l'eval, PUIS tu recuperes l'exception, puis tu continues" et je ne vois
pas trop comment faire...
Avatar
Paul Gaborit
À (at) Tue, 27 Oct 2009 18:36:21 +0000 (UTC),
(Marc Espie) écrivait (wrote):
In article ,
Paul Gaborit <Paul.Gaborit+ wrote:

À (at) Tue, 27 Oct 2009 12:01:49 +0000 (UTC),
(Marc Espie) écrivait (wrote):
J'ai un bout de code qui recupere les exceptions a coup de
eval {....die ...};
if ($@) {
...
die ... # rethrow
}

probleme: comment debugguer tout ca ?

j'aimerais bien que perl -d me montre une stack trace a l'endroit du
premier die...



Il est encore possible d'utiliser $SIG{__DIE__} pour capter 'die'
(cf. perlvar) même si la documentation dit qu'un jour cette
possibilité n'existera plus dans les 'eval'.

Mais je ne comprends pas le besoin... Pourquoi ne pas instrumenter
l'appel à 'die' lui-même en lui passant une référence comme argument
(cf. perldoc -f die) ? Dans cette référence on peut stocker toute
l'information nécessaire...



En fait, j'ai ete un peu vite en description... ce qui m'interesse, c'est
un cas ou ce n'est pas moi qui suis a l'origine du die. En l'occurrence,
un $object->method avec $object qui vaut undef...

Et perl -d me donne un backtrace... du 2e die. Et j'aimerais non pas capter
die, mais pouvoir dire "si debugguer, alors tu me fais un backtrace dans
l'eval, PUIS tu recuperes l'exception, puis tu continues" et je ne vois
pas trop comment faire...



Sans l'avoir testé via le debugger (je ne l'utilise quasiment jamais),
je pense que le code suivant peut aider :

sub f {
die "erreur";
}
eval {
$SIG{__DIE__} = sub {
warn "die handler: @_n"; # !!!
};
f();
}
if ($@) {
warn "$@n";
}

Dans la subroutine anonyme attachée à __DIE__ on voit très bien toute
la pile d'appel dans le contexte du premier 'die' (en passant par
f()). Cette pile est certainement visible dans le debugger... mais
aussi via le module Carp si ne souhaite pas utiliser le debugger :

use Carp;
sub f {
die "erreur";
}
eval {
$SIG{__DIE__} = sub {
Carp::cluck "die handler: @n";
};
f();
};
if ($@) {
warn "$@n";
}


--
Paul Gaborit - <http://perso.mines-albi.fr/~gaborit/>
Perl en français - <http://perl.mines-albi.fr/>
Avatar
espie
In article ,
Paul Gaborit <Paul.Gaborit+ wrote:
Sans l'avoir testé via le debugger (je ne l'utilise quasiment jamais),
je pense que le code suivant peut aider :


Heureux homme... moi je n'ai pas le choix, avec du gros, gros code en
production, quand d'aventure ca plantouille, je peux difficilement demander
mieux a mon bug-reporter que de me faire un perl -d....

sub f {
die "erreur";
}
eval {
$SIG{__DIE__} = sub {
warn "die handler: @_n"; # !!!
};
f();
}
if ($@) {
warn "$@n";
}

Dans la subroutine anonyme attachée à __DIE__ on voit très bien toute
la pile d'appel dans le contexte du premier 'die' (en passant par
f()). Cette pile est certainement visible dans le debugger... mais
aussi via le module Carp si ne souhaite pas utiliser le debugger :

use Carp;
sub f {
die "erreur";
}
eval {
$SIG{__DIE__} = sub {
Carp::cluck "die handler: @n";
};
f();
};
if ($@) {
warn "$@n";
}


Bon, j'essaierai sans doute ca ce week-end et je te tiens au courant...
Avatar
Paul Gaborit
À (at) Wed, 28 Oct 2009 07:46:08 +0000 (UTC),
(Marc Espie) écrivait (wrote):

In article ,
Paul Gaborit <Paul.Gaborit+ wrote:
Sans l'avoir testé via le debugger (je ne l'utilise quasiment
jamais), je pense que le code suivant peut aider :



Heureux homme... moi je n'ai pas le choix, avec du gros, gros code en
production, quand d'aventure ca plantouille, je peux difficilement demander
mieux a mon bug-reporter que de me faire un perl -d....



C'est quoi un "bug-reporter" ? C'est un utilisateur à qui tu demandes
de t'envoyer une trace lors d'un plantage ?

Dans ce genre de situations, je préfère utiliser la technique que je
donnais pour dérouter les appels à "die" et enregistrer moi-même les
informations qui m'intéressent dans un fichier de log.

[...]
Bon, j'essaierai sans doute ca ce week-end et je te tiens au
courant...



Tu m'en diras des nouvelles ! ;-)

--
Paul Gaborit - <http://perso.mines-albi.fr/~gaborit/>
Perl en français - <http://perl.mines-albi.fr/>
Avatar
espie
Avec pas mal de delai, j'ai finalement resolu mon probleme differemment.

La ou j'avais:
eval {
# This is the actual very small loop that adds all packages
$state->tracker->add_sets(@todo2);
while (my $set = shift @todo2) {
unshift(@todo2, install_set($set, $state));
}
};
my $dielaster = $@;

j'ai maintenant:

my $code = sub {
# This is the actual very small loop that adds all packages
$state->tracker->add_sets(@todo2);
while (my $set = shift @todo2) {
unshift(@todo2, install_set($set, $state));
}
};

if ($state->{defines}->{debug}) {
&$code;
} else {
eval { &$code; };
}
my $dielater = $@;



comme souvent, suffit de nommer ce avec quoi on bosse, et ca ne me coute
pas plus cher de dire aux gens de relancer ma commande avec -F debug
pour avoir un backtrace raisonnable...

Je pourrais carrement rendre ca automatique a coup de test sur le
hash %DB::sub, mais je prefere laisser ca en manuel pour l'instant...
Avatar
Paul Gaborit
À (at) Sat, 14 Nov 2009 10:51:51 +0000 (UTC),
(Marc Espie) écrivait (wrote):

j'ai maintenant:

my $code = sub {
# This is the actual very small loop that adds all packages
$state->tracker->add_sets(@todo2);
while (my $set = shift @todo2) {
unshift(@todo2, install_set($set, $state));
}
};

if ($state->{defines}->{debug}) {
&$code;
} else {
eval { &$code; };
}
my $dielater = $@;



Pourquoi pas si cela te semble plus simple.

Juste une remarque sur l'utilisation de :

&$code;

Pourquoi ne pas faire au moins :

&$code();

ou mieux :

$code->();

C'est plus clair car on voit immédiatement que c'est un appel de
fonction et ça n'utilise pas le mécanisme caché du '&'. À moins
évidemment que ne ce soit volontaire...

--
Paul Gaborit - <http://perso.mines-albi.fr/~gaborit/>
Perl en français - <http://perl.mines-albi.fr/>
Avatar
espie
In article ,
Paul Gaborit <Paul.Gaborit+ wrote:
Juste une remarque sur l'utilisation de :

&$code;

Pourquoi ne pas faire au moins :

&$code();

ou mieux :

$code->();

C'est plus clair car on voit immédiatement que c'est un appel de
fonction et ça n'utilise pas le mécanisme caché du '&'. À moins
évidemment que ne ce soit volontaire...



C'est volontaire: c'est du refactoring bete, et precisement, j'ai envie
de rediriger vers &code() "comme si" c'etait ce qui etait la depuis le
debut. Apres, je vais faire une passe de re-nettoyage (en l'occurrence, j'ai
deux programmes qui commencent a avoir enormement de code en commun dans
cette zone, donc, ca va finir en application du Design Pattern
Template Method de facon tres nette).