Thursday, December 9, 2010

Day 9: another debugging story

Nobody wants to do it, but sometimes there is no way around: overwriting a sub routine of a (CPAN) module. In our case we had to fiddle around in URI::Escape, because we wanted to port our legacy web framework to Plack. And our "non standard" UTF8 handling made same changes necessary. :)

So, everything worked and we went along with other things. A few weeks later, it suddenly stopped working. We used "git bisect" to identify the guilty commit - code, that had nothing to do with our web framework. But the code was using URI::http and somehow ended using URI::_query too, which is importing uri_unescape from URI::Escape. (I do not remember the exact details, so if this is confusing, I may have missed/mixed some facts.)

But how did we find this out? I used Devel::Loading to print out the order of loading each module (CPAN and our own code). It was quite a long list. And one difference between the two commits was the relative order of URI::_query versus our module that was overriding uri_unescape.

How does Devel::Loading work? Does it overwrite 'use' and 'require'?

No. You can put a code reference into @INC. See 'perldoc -f require' for the glory details. But here is a small example:
#!/usr/bin/perl

use strict;
use warnings;

BEGIN {
    unshift @INC, sub {
        my ($own_code, $module) = @_;
        print "Tried to use $module.\n";
        return undef;
    };
}

use Data::Dumper;

It has the following output:
Tried to use Data/Dumper.pm.
Tried to use Carp.pm.
Tried to use Exporter.pm.
Tried to use XSLoader.pm.
Tried to use bytes.pm.
Tried to use overload.pm.
Tried to use warnings/register.pm.

When the coderef returns 'undef', the next entry in @INC is queried.

Links:
Feedback:
How did you like today's entry? Shall I tell more stories or stick to the more neutral, example based approach? I'm looking forward to your comments.

PS: "We" in this entry means our Perl architecture team at work. Our employer has some open positions. Contact me, if you are interested or have some questions.

3 comments:

  1. I remember I read about this some time ago, but totally forgot it. It's always good to get attention again for the things you rarely need... until tomorrow ;-)

    I'm following this series from Day 1 and like it very much. My personal gem was learning about inheritable DATA sections on Day 4, a feature I probably will use soon.

    ReplyDelete
  2. Hey Henning,

    thanks for the feedback. I hope I can deliver at least one more gem.

    ReplyDelete
  3. Hello, I just discovered this calendar. I found really interesting Day 1 (and lib::abs from comments), day 4 and especially day 6. I just have some use for code analysis like that.

    ReplyDelete