Можно ли запускать только определенный саб под отладчиком? - PullRequest
3 голосов
/ 18 июня 2019

Я хочу напечатать трассировку стека только определенной подпрограммы. Является ли это возможным ? Скрипт работает под Perl без опции -d.

Простой пример:

#!/usr/bin/env perl

foo();

sub foo {
    print "Hello world\n";
    # enable debugger from this moment with PERLDB_OPTS='NonStop frame=1'
    bar();
    # disable debugger from this moment
    return;
}

sub bar {
    print "Just another Perl hacker\n";
    return;
}

Ожидаемый результат:

$ perl test.pl 
Hello world
    entering main::bar
Just another Perl hacker

Я пытался играть с $ENV{PERL5DB}, но без эффекта:

$ENV{PERL5DB}='sub DB::DB {} sub sub {print ++$i, " $sub\n"; &$sub}';
bar();
$ENV{PERL5DB} = undef;

Ответы [ 3 ]

3 голосов
/ 19 июня 2019

Вы можете просто установить $DB::frame непосредственно из своего кода:

#!/usr/bin/env perl

foo();

sub foo {
    print "Hello world\n";
    $DB::frame = 1;
    bar();
    $DB::frame = 0;
    return;
}

sub bar {
    print "Just another Perl hacker\n";
    return;
}

Это может быть выполнено следующим образом:

$ PERLDB_OPTS=NonStop perl -d try.pl
Hello world
   entering main::bar
Just another Perl hacker

Вот и все.


Если вы хотите сделать это вручную и определить свой собственный отладчик, вы можете сделать это следующим образом:

#!/usr/bin/env perl

foo();

sub foo {
    print "Hello world\n";
    $DB::xtrace = 1;
    bar();
    $DB::xtrace = 0;
    return;
}

sub bar {
    print "Just another Perl hacker\n";
    return;
}
$ PERL5DB='BEGIN { package DB; sub DB {} sub sub { print STDERR "    entering $sub\n" if $xtrace; &$sub } }' perl -d try.pl
Hello world
    entering main::bar
Just another Perl hacker
1 голос
/ 18 июня 2019

Вы выиграете от конвертации вашего скрипта в модуль.

Проблема, с которой вы столкнулись, заключается в том, что foo() вызывается напрямую, как только Perl входит в среду выполнения.Но это не то поведение, которое вам нужно с точки зрения отладки.

Цель модуля - разрешить обрабатывать большую часть кода как встроенный модуль и разрешить запуск или запуск кода толькозапускается, если скрипт запускается напрямую, но не запускается, если вместо этого скрипт загружается как модуль.Делая это, вы можете написать набор тестов для кода modulino, оставив только минимальный стартовый код вне досягаемости модульных тестов.

Здесь существует одна из нескольких статей по этой теме: https://perlmaven.com/modulino-both-script-and-module

Для ваших целей модуль modulino позволяет вам более избирательно относиться к тому, что вы запускаете с помощью отладчика Perl.

Если вы структурируете свой код следующим образом, вы будете более успешны:

package MyModulino;
use parent 'Exporter';
our @EXPORT = qw(foo bar);

sub foo {
    print "Hello world\n";
    # enable debugger from this moment with PERLDB_OPTS='NonStop frame=1'
    bar();
    # disable debugger from this moment
    return;
}

sub bar {
    print "Just another Perl hacker\n";
    return;
}

package main;

if(!caller) {
    MyModulino->import();
    foo();
}

Теперь вы можете сделать это:

perl -I/some/path/to/script -e 'do "scriptname"; MyModulino::bar()'

Другими словами, теперь вы можете рассматривать scriptname, что бы это ни было, как модуль с пакетом с именем MyModulino, и вы можете вызывать bar() напрямую, а не полагаться на foo(), чтобы позвонить.Вызов foo() происходит только в том случае, если caller() возвращает false, что он будет делать, если вы запускаете программу напрямую, но не будет, если вы вызываете ее как модуль.

Обрабатывая scriptname какмодуль, вызов foo() не выполняется неявно, и ваш код отладчика может вызывать bar() из пакета MyModulino.

Этот один лайнер должен перенаправить вас в отладчик, не вызвав foo().

perl -d -I/path/to/script -e 'do "scriptname"; MyModulino::bar()'

Вы можете комбинировать эту технику вместе с Test::MockModule, чтобы высмеивать части стека вызовов, которые вам не нужны при тестировании bar().Но когда вы начинаете идти по этому пути, вам действительно следует потратить время на реализацию этих стратегий в автоматизированном тестовом сценарии.В этом случае по-прежнему действует совет «modulino».

1 голос
/ 18 июня 2019

Это просто вопрос о том, как произвести трассировку стека? Для этого вам не нужен отладчик.

use Carp;
sub bar {
    Carp::cluck("entering main::bar");
    ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...