IIDE/Pro v9.0.1 remote debugging for perl won't stop at breakpoints

I use Komodo IDE pro v9.0.1 for developing and debugging both php and perl. I am unable to get breakpoints to reliably pause execution in Perl. Php debugging on the same configuration works well. The remote system is running CentOS, and I run the IDE on Windows 7 Pro. I have confirmed that the connection (through port 9000) works, and the Windows host IDE has “Listening for debugging connections” working. I can step through some code by setting “Break on first executable line” in the “Preferences->Debugger” dialog and then stepping through the code.

Most breakpoints seem to be simply ignored. I can see them in the “Breakpoints” tab of the IDE, but they have no effect on execution. The URL mappings all seem ok. For many perl function calls, I simply cannot step into the code – my attempts simply run the function to completion.

I’ve confirmed that the breakpoints are visible in the “Breakpoints” tab of the IDE, and their filenames seem reasonable. They simply have no effect.

One thing I’m struggling with is the apparent absence of log files, especially on the remote (Linux) side. Other IDEs that support remote debugging often allow writing a log file so that negotiations between the remote and local systems can be tracked.

The ability to set and then step through breakpoints in Perl is a vital piece of IDE functionality, it is essentially worthless to me without it. Any suggestions?

First things first - can you verify that a debugging connection is made? When Komodo connects to a remote debugging process it will open your debug pane; is this happening?

Note you can specify a debug log under Prefs > Languages > Perl.

To clarify my thread-starter, indeed I do have a debugging connection open. When I change the debugger preferences to “Break on first executable line” and start the perl on the remote system (using “perl -d …”, I’m able to step through some of the code. The debugging connection seems to be working, and the URL mappings are working as expected.

I appreciate the pointer to the debug log, hopefully that will help.

I’ve also confirmed that the appropriate contents are in /usr/lib64/perl5/vendor_perl/Komodo. I’m running perl v5.10.1.

Just a follow-up note regarding the perl log file – the preferences setting you indicate seems to affect only perl code run on the local (Windows) machine. During a remote debugging session, there is no local perl executed and no log file is created.

It would be much more helpful if there is a way to configure the remote perl so that it writes a log file pertaining to the perl running on the remote system.

Could you see if placing a breakpoint in the file that gets triggered by Break on first executable line works?

I think it does, but let me confirm that and update the thread. I appreciate your attention.

UPDATED: Yes, it does stop at the first breakpoint, even while the debugger mode is “Run to first breakpoint” (as expected).

That line contains a function call, and attempting to step into the function call runs through several lines and then stops at a function call to another built-in perl method.

Here’s a fragment of the top-level script:

use strict;
use warnings;
use FindBin;
use Getopt::Long();

use lib "$FindBin::Bin/lib";
use lib "$FindBin::Bin/../lib";
use DB::Cyber;
use Config::Simple;
# ...
my $cyberDBH = DB::Cyber::setupCyberDB($opts,\@cyberData);

The breakpoint is set at the last line above (my $cyberDBH …).

The referenced code (DB::Cyber) is available and open in the IDE.

Here is the code called from the top level:

#...
sub setupCyberDB {
    my ($config,$data) = @_;
    return if (! defined($config->{instance_type}) || $config->{instance_type} !~ m/^(test|dev)$/);
    $data ||=[];
    my ($connection,$driver,$cyberDBName,$host) = split(/[:;]/,$config->{idbconnect});
    DB::Common::echoToMySQL(qq{'DROP DATABASE IF EXISTS `$cyberDBName`;'}) or
        die "Unable to drop database $cyberDBName:$DBI::errstr";
    DB::Common::echoToMySQL(qq{'CREATE DATABASE `$cyberDBName`;'}) or
        die "Unable to create database $cyberDBName:$DBI::errstr";
    
    
    my $adminDBH = DBI->connect ($config->{idbconnect}, $config->{dbadminuid}, $config->{dbadminpwd}, {PrintError => 0}) or die "Unable to connect to admin db: $DBI::errstr";
    # ...

When I attempt to step into “setupCyberDB” (from the breakpoint), the IDE takes me inside the DBI::connect method of the last line. Breakpoints in setupCyberDB have no effect.

When the debugger pauses inside DBI::connect, the callstack (in the debugger pane) shows the call to setupCyberDB and lets me navigate there. When I attempt to step out of DBI::connect, it runs the rest of the code in setupCyberDB and again pauses in DBI::connect. There seems to be no way to step through setupCyberDB one line at a time.

Breakpoints seem to work inside the DBI methods. Interestingly, when I attempt to step over the line in the outermost script from the breakpoint (my $cyberDBH …), the debugger pauses at the first line of DBI::connect, exactly as if I had clicked “step into” instead of “step over”.

Everything you say points to the file mapping not being set up correctly. I bet when you step through your code when using Break on first executable line it will open files that you already had opened. You need to check what file path its breaking on and then set up the appropriate mapping under Prefs > Mapped URIs. You may also want t ocheck the “For URIs where no mapping yet exists” setting on that screen.

I’ve rechecked the mapped uris, they look good to me.

Here are the relevant entries:

file://///localhost.localdomain/media/imars.trunk => C:\projects\imars.trunk
file://///localhost.localdomain/usr/local/lib64/perl5 => C:\local_projects\usr\local\lib64\perl5

I always keep “For URIs where no mapping yet exists” set to “Ask me what to do”.

The first entry is how the top-level script is found. When I removed that entry, I was prompted (as expected) to map it. The script being skipped is in a subdirectory of that tree (file://///localhost.localdomain/media/imars.trunk/source/t/lib/DB => C:\projects\imars.trunk\source\t\lib\DB)

I agree it sounds like a URI mapping issue, but I don’t think it’s cockpit error. I even tried adding a URI mapping to the specific directory:

file://///localhost.localdomain/media/imars.trunk/source/t/lib/DB => C:\projects\imars.trunk\source\t\lib\DB

Still no joy. Note that the file being skipped is accessible from the callstack pane, so it looks to me as though the IDE is aware of the mapping.

If there was a way to log the remote system’s behavior (inside /usr/lib64/perl5/vendor_perl/Komodo/perl5db.pl), it might reveal more about what’s happening (or not happening).

I do notice that the remote url is different between perl and php. For the php URI Mapping entries, each begins with
“file://///127.0.0.1/…”
whereas the perl entries begin with:
" file://///localhost.localdomain/…"

I know that 127.0.0.1 is a synonym for localhost.localdomain, but the difference catches my eye.

I’ve found and locally fixed the issue.

First, a documentation note for the Komodo team. Logging of the remote system behavior during a remote debugging session can be enabled by adding a “LogFile=/path/to/logfile” entry to the PERLDB_OPTS setting. On my (linux) system, I used the following:

export PERLDB_OPTS="RemotePort=localhost.localdomain:9000 async=1 LogFile=/var/log/komodo/komodo_perl.log"

This causes a log file (“komodo_perl.log”) to be written to the designated location.

The resulting logfile pointed clearly to the issue. There is a bug at or near line 2397 of perl5db.pl, as distributed by ActiveState. The existing code causes ANY package named “DB” to be skipped by the IDE. The intent is to skip the Komodo debugging code itself, kept in the badly-named “DB” package distributed by ActiveState. In my case, the code under development is kept in an independent package also named “DB”.

The fix I installed was to inspect the $filePath variable for the element “Komodo”, since the install path of the debugging module on my system is “/usr/lib64/perl5/vendor_perl/Komodo”. Here is the code (in context) that works on my system:

    #...
    if (($single || $signal)
        && ($pkg eq 'DB::fake'|| !(($pkg =~ /^DB::/) && ($filePath =~ /Komodo/)))
        && !$inPostponed) {
    #...

With this change in place, the IDE now steps into code and pauses at breakpoints as desired.

That’s some impressive digging! Thanks @csid_tom, glad you figured it out!

Unfortunately it’s too late to push this change for the next release, which is due veeery soon, but I’ll be sure to add this for the next one.

Opened a bug here: https://github.com/Komodo/KomodoEdit/issues/309