Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Int-3 equivalent?

by BrowserUk (Patriarch)
on Jun 09, 2004 at 23:28 UTC ( [id://362933]=perlquestion: print w/replies, xml ) Need Help??

BrowserUk has asked for the wisdom of the Perl Monks concerning the following question:

This thought was triggered by reading C/C++ type assert() in Perl?.

I use the debugger when I have to. Which generally speaking is fairly rarely. I'm quite comfortable using CLI debuggers, having started doing so when there was literally no alternative; programming in assembler. Perl's debugger is really very powerful and very convenient to use--once you get to the point you need to be at--it's getting there that is the problem.

There are various techniques for running to particular places in the code. Breakpoints, watches etc. The problem with them is that you have to re-type all your commands once you made a change. Yes, you can load commands from a file, but there's no really convenient way to save them to a file once you interactively decided what sequence of commands is required to get you where you need to be. CL histories don't help much either because they also tend to keep all the stuff that wasn't useful.

Long story short: Is there any perl equivalent of the int3 instruction?

Something that will drop you into the debugger when it is encountered in the source at the point that it is encountered so that you can easily continue debugging from that point?

I've tried die, but by that point the internal state is screwed.

What's needed is a way to tell the debugger to run the program non-interactively until the "int-3" instruction is encountered and then break into the debugger at that point. It should be possible to add a line like

... int3 if not exists $hash{'thing'} or $hash{'thing'} ne 'something'; ...

Then perl -d=go script.pl and the program runs normally (if slowly) until one of the int3 assertions is true.

Is there already a way to do this easily that I have missed?

If not, can anyone see an easy way to implement it?

Does anyone else think that this would be useful?

Clarification:

Stated another way, what I'm looking for is a simple mechanism to effect a breakpoint, from with the perl source that will drop me into the debugger when it is encountered. And do so such that the environment in place when the breakpoint is encountered, is still intact. As it would be if I had added the breakpoint via the degugger command line but is not the case with die or carp.

This way I can investigate the reason why things are not as they should be. Inspect variables, change the values etc. and then continue the program to see if I've found and fixed the cause. This is also not possible after a die or Carp.

Essentially, I am looking for a way to embed debugger commands directly in the source rather than issuing them from teh debugger prompt or putting them into a separate debugger script.

It just seems it would easier, more natural and intuative to maintain debugger commands in-place in the script being debugged. That way, you don't have to adjust the line number on breakpoint every time you add or remove a line. Changing the conditions on break and watch points as you home in on the source of the problem is much easier if the changes are located in the context of the code rather than in a separate script or trying to remember them each time you re-run the debug session.

Does that make any sense to anyone else?


Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"Think for yourself!" - Abigail

20040611 Edit by Corion: Fixed runaway <i> tag

Replies are listed 'Best First'.
Re: Int-3 equivalent?
by tachyon (Chancellor) on Jun 10, 2004 at 01:12 UTC

    You can get the desired behaviour as follows. Set perldb.ini as follows (in the current dir):

    C:\>type perldb.ini $ENV{PERLDB_OPTS}="NonStop frame=2";

    Because perl5db.pl (the debugger in X:\\Perl\lib\perl5db.pl on Win32) is Unix centric it will refuse to read this file due to permissions being too open. A quick patch is to skip the is_safe_file() test on Win32 circa line 317 with something like:

    unless (is_safe_file($file) or $^O =~ m/Win32/ ) {

    There are other options to set the NonStop feature (ie .perldb and set PERLDB_OPTS env var) but that was the only one that worked (after the patch) on Win32 and I was too lazy to debug the debugger any deeper. Anyway here is an example that happily flips into and out of the interactive debugger:

    C:\>type test.pl print "Hello\n"; print "World!\n"; assert( 1 == 0 ); print "In interactive Debugger!\n"; $a = "Still in debugger!\n"; print $a; assert( 1 == 1 ); print "Escaped Debugger!\n"; print "Still Free!\n"; assert( 0 ); print "Debugger again!\n"; sub assert { $DB::single = $_[0] ? 0 : 1 } C:\>perl test.pl Hello World! In interactive Debugger! Still in debugger! Escaped Debugger! Still Free! Debugger again! C:\>perl -d test.pl Default die handler restored. Package test.pl. Hello World! entering main::assert exited main::assert 4: print "In interactive Debugger!\n"; DB<1> n In interactive Debugger! 5: $a = "Still in debugger!\n"; DB<1> n 6: print $a; DB<1> n Still in debugger! 7: assert( 1 == 1 ); DB<1> c entering main::assert exited main::assert Escaped Debugger! Still Free! entering main::assert exited main::assert 11: print "Debugger again!\n"; DB<1> c Debugger again! Debugged program terminated. Use q to quit or R to restart, use O inhibit_exit to avoid stopping after program termination, h q, h R or h O to get additional info. DB<1> q C:\>

    cheers

    tachyon

      Yes, the exact equivalent of what the OP was looking for can be done with $DB::single = 1. I often insert this into my code when running it under the debugger; there's no compile/link cycle to worry about, so this is convenient enough. (tachyon's response already contained this information, but I never bother with perldb.ini files or anything.)

      Another useful hint is to put this chunk of code near the beginning of your file:

      BEGIN { $SIG{__WARN__} = sub { print STDERR @_; $DB::single = 1; } }
      This will make you drop into the debugger immediately after printing a warning. (It won't take effect until the following statement, so you don't have to worry about stepping out of the BEGIN block or anything.)

      My other main tool for using the perl debugger is my debug script, which you can simply add as a prefix to your perl command line and it'll pop up emacs running the debugger in a window. (Note that the script is also for running gdb on non-perl files, so watch out if it says (gdb) instead of DB<>.)

      Update: I can't believe I originally wrote $ENV{__WARN__} instead of $SIG{__WARN___}...

      That's neat! tachyon++

      I looked at perldb.ini a long while ago but in never seemed to work. Now I know why:)

      Wrap that little assert sub up in a source filter along with the code to read and invoke comment embedded db commands and it has the making of a really useful tool.

      Off to read more...Thanks.


      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "Think for yourself!" - Abigail
      Nice trick!

      On linux I used:

      BEGIN { $ENV{PERLDB_OPTS}="NonStop frame=2"; }
      which seems to work fine. This technique also works with the ptkdb debugger.

      Using it this way with ptkdb on linux, the debugger window appears at the start of the program. I can press 'Run' and the program runs until the equivalent of a 'breakpoint', which is set with the assert() routine.

      I wonder if there is a way to get the ptkdb window to appear for the first time when the assert function is called? That way, my program could run normally and only pull up ptkdb when something goes wrong.

      It should work perfectly the first time! - toma

      (++) Definitely the sort of thing I was seeking for a (very) long time!

      Would it be nice having a Categorized Q&A entry of it?

      Update: The perl5db.pl included into ActivePerl 5.8.3, is v1.23 and the line number is 1271. Personally, I prefered alter function is_safe_file with the following first line:

      return 1 if $^O =~ m/Win32/;
      HTH, Dominique
      Excellent! I wish I could give more than one ++.

      For anyone else looking, you could also set the environment variable PERL5DB_OPTS="NonStop frame=2", then execute the script with the -d command line switch (perl -d script.pl).

Re: Int-3 equivalent?
by tachyon (Chancellor) on Jun 10, 2004 at 00:13 UTC

      Unfortunately neither really achieve my aim. Carp::Assert will break out of the running program if the condition fails and, if your running under -d, then you'll end up in the debugger. The problem is that you cannot then continue the program or even inspect the state that was in play when the assertion failed. It in no better than  die if .... in this respect.

      Devel::StealthDebug is basically print statements in comments enabled or disabled through a source filter. A nice idea and implementation, but it doesn't achieve my aim.

      I'll update the OP to make this clearer.


      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "Think for yourself!" - Abigail
Re: Int-3 equivalent?
by borisz (Canon) on Jun 09, 2004 at 23:58 UTC
    I'm not sure if this is what you asked for,
    kill 11 => $$ if not exists $hash{'thing'} or $hash{'thing'} ne 'somet +hing';
    Boris

      Perhaps SIGTRAP (== 5 here) is more appropriate than segfault. It's not POSIX but it is susv2, and described as "Trace/breakpoint trap" in man 7 signal. The default action is to core and exit, but a %SIG{TRAP} handler can deal with that.

      After Compline,
      Zaxo

      kill 11 terminates the program and the debugger. Not at all what I am looking for.

      I've update the OP in an attempt to make things a bit clearer. Whether I've succeeded you'll have to judge for yourself:)


      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "Think for yourself!" - Abigail

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://362933]
Approved by Thelonius
Front-paged by Thelonius
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (3)
As of 2024-04-19 21:49 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found