Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't set breakpoints in code loaded via eval that contains #line directives #34

Open
mbarbon opened this issue May 10, 2018 · 5 comments

Comments

@mbarbon
Copy link
Contributor

mbarbon commented May 10, 2018

Devel::Camelcade version 2017.100.3

I can reproduce this issue when using ModPerl::Registry. I do not have a simple test case yet, but hopefully the description below is enough for you to understand the issue.

Some context: ModPerl::Registry compiles and caches CGI scripts under mod_perl for faster execution. For example this script:

#!/usr/bin/env perl

print "Content-Type: text/plain\n";
print "\n";
print "Hello, world!\n";

is converted to

package ModPerl::ROOT::ModPerl::RegistryBB::home_mattia_devel_dbgp_apache2_2dcamelcadedb_t_htdocs_registrybb_cgi_2epl;sub handler {local $0 = '/home/mattia/devel/dbgp/apache2-camelcadedb/t/htdocs/registrybb/cgi.pl';
#line 1 /home/mattia/devel/dbgp/apache2-camelcadedb/t/htdocs/registrybb/cgi.pl
#!/usr/bin/env perl

print "Content-Type: text/plain\n";
print "\n";
print "Hello, world!\n";

}

and loaded via eval STRING.

From my debugging, the issue is that Perl does not call DB::postponed for code loaded via eval STRING, so there is no mapping for the file in %_paths_to_perl_file_id_map, and the breakpoint is silently ignored.

@hurricup
Copy link
Collaborator

@akjohnston
Copy link

Hi,
Is there any chance that we can update the plugin so that this is fixed directly and debugging will work with code loaded using ModPerl::Registry or ModPerl::RegistryBB?

I have been asked to help support an existing system, and fundamentally changing the source code to make debugging work is not an option. Mattia (@mbarbon) has done great work writing a wrapper which just loads via the apache .conf files, but it doesn't work on our source because of the problem he has reported.

Please could someone look at the plugin and see if we can design a proper fix which doesn't require me to change our Perl source? I am very happy to help in any way I can, but although I'm an experienced developer in other languages I'm a newbie to Perl and I can't tackle this directly myself.

Thanks
Andrew

@hurricup
Copy link
Collaborator

Doubt it can be fixed on the debugger side. Because we are talking about arbitrary changing of line numbers by the module and compilation of file form unknown source. I can imagine few hacks, but I believe this is not a good way.

@hurricup
Copy link
Collaborator

In default case ModPerl::RegistryCooker::convert_script_to_compiled_handler should be patched according to the manual above. It should notify debugger after compile()

@akjohnston
Copy link

I'm trying to develop a new version of ModPerl::Registry as instructed, but I'd appreciate a check on what I'm doing. I have created a new version which subclasses RegistryCooker and overrides convert_script_to_compiled_handler. That contains the following section:

` my $base = File::Basename::basename($self->{FILENAME});
my $nph = substr($base, 0, 4) eq 'nph-' ? '$_[0]->assbackwards(1);' : "";
my $script_name = $self->get_script_name || $0;

my $eval = join '',
    'package ',
    $self->{PACKAGE}, ";",
    "sub handler {",
    "local \$0 = '$script_name';",
    $nph,
    $shebang,
    $line,
    ${ $self->{CODE} },
    "\n}"; # last line comment without newline?

$rc = $self->compile(\$eval);
return $rc unless $rc == Apache2::Const::OK;
$self->debug(qq{compiled package \"$self->{PACKAGE}\"}) if DEBUG & D_NOISE;`

I think I have to modify this as follows, but I'm really not 100% sure:

` my $eval = join '',
'package ',
$self->{PACKAGE}, ";",
"sub handler {",
"local $0 = '$script_name';",
$nph,
$shebang,
$line,
${ $self->{CODE} },
"\n}"; # last line comment without newline?

$rc = $self->compile(\$eval);
           
# IntelliJ debug support
{
    no strict 'refs';
    my $glob = *{'::DB::template_handler'};

    if ($glob && *{$glob}{CODE})
    {
        *{$glob}{CODE}->($self->{FILENAME}, $line);
    }
}
# end debg support
           
return $rc unless $rc == Apache2::Const::OK;
$self->debug(qq{compiled package \"$self->{PACKAGE}\"}) if DEBUG & D_NOISE;` 

Does that look right? Do I also need to add some code to open the connection to the debugger, or can I do this in the same way as before?

Please help,
Thanks
Andrew

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants