Skip Menu |

This queue is for tickets about the Net-DNS CPAN distribution.

Report information
The Basics
Id: 123702
Status: resolved
Priority: 0/
Queue: Net-DNS

People
Owner: Nobody in particular
Requestors: daa [...] open.ch
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: 1.13
Fixed in: (no value)



Subject: 'use base' should not be used in packages with several subpackages defined
We have been debugging a very rarely occurring bug with Net::DNS v1.12 and v1.13 and perl v5.20. *** FATAL PROGRAM ERROR!! Unknown instance method 'rcode' *** which the program has attempted to call for the object: *** . IN OPT *** *** THIS IS A BUG IN THE CALLING SOFTWARE, which incorrectly assumes *** that the object would be of a particular type. The type of an *** object should be checked before calling any of its methods. *** Attempt to reload Net/DNS/RR/OPT.pm aborted. Compilation failed in require at (eval 172) line 2. Net::DNS::RR 1569 at /opt/OSAGperlm/lib/Net/DNS/Header.pm line 172. Net::DNS::Header::rcode(Net::DNS::Header=REF(0x32d9580), "FORMERR") called at /opt/OSAGperlm/lib/Net/DNS/Packet.pm line 273 Net::DNS::Packet::reply(Net::DNS::Packet=HASH(0x3eadff8)) called at /opt/OSAGperlm/lib/Net/DNS/Nameserver.pm line 193 Net::DNS::Nameserver::make_reply(Net::DNS::Nameserver=HASH(0x2ce2410), Net::DNS::Packet=HASH(0x3eadff8), "127.0.0.1", HASH(0x35eca50)) called at /opt/OSAGperlm/lib/Net/DNS/Nameserver.pm line 410 Net::DNS::Nameserver::udp_connection(Net::DNS::Nameserver=HASH(0x2ce2410), IO::Socket::INET=GLOB(0x3eb5d08)) called at /opt/OSAGperlm/lib/Net/DNS/Nameserver.pm line 464 Net::DNS::Nameserver::loop_once(Net::DNS::Nameserver=HASH(0x2ce2410), 10) called at /opt/OSAGperlm/lib/Net/DNS/Nameserver.pm line 541 We have been able to track the bug down to the following: 1) Net/DNS/RR/OPT.pm and Net/DNS/DomainName.pm declares several packages in the same file and is using "use base" to load the parent class (which is in the same file). 2) Our program does daemonize and change its GID/UID to a user which is not able to read the current working directory. 3) This triggers a side effect of "use base" which will fail as the current working directory is not readable when requiring Net::DNS::RR::OPT::DHU which is actually in OPT.pm which has already been loaded. The fix is to use either a newer version of perl which does not automatically include the current working directory in the @INC or to use "use parent -norequire" instead of use base. This is described here: http://perldoc.perl.org/parent.html The attached patch does exactly does, it will use 'use parent -norequire' for all packages which have the parent in the same .pm file declared. We have been fixing a similar issue in libwww-perl recently: https://github.com/libwww-perl/libwww-perl/pull/259/files Please let me know if you need further information on this.
Subject: Net-DNS-v1.13.patch
diff -ur Net-DNS-1.13/lib/Net/DNS/DomainName.pm Net-DNS-1.13-patched/lib/Net/DNS/DomainName.pm --- Net-DNS-1.13/lib/Net/DNS/DomainName.pm 2017-10-18 11:00:36.000000000 +0200 +++ Net-DNS-1.13-patched/lib/Net/DNS/DomainName.pm 2017-11-21 15:39:51.000000000 +0100 @@ -155,7 +155,7 @@ ######################################## package Net::DNS::DomainName1035; -use base qw(Net::DNS::DomainName); +use parent -norequire, qw(Net::DNS::DomainName); =head1 Net::DNS::DomainName1035 @@ -217,7 +217,7 @@ ######################################## package Net::DNS::DomainName2535; -use base qw(Net::DNS::DomainName); +use parent -norequire, qw(Net::DNS::DomainName); =head1 Net::DNS::DomainName2535 diff -ur Net-DNS-1.13/lib/Net/DNS/RR/OPT.pm Net-DNS-1.13-patched/lib/Net/DNS/RR/OPT.pm --- Net-DNS-1.13/lib/Net/DNS/RR/OPT.pm 2017-10-18 11:00:36.000000000 +0200 +++ Net-DNS-1.13-patched/lib/Net/DNS/RR/OPT.pm 2017-11-21 15:38:33.000000000 +0100 @@ -230,10 +230,10 @@ package Net::DNS::RR::OPT::DHU; # RFC6975 -use base qw(Net::DNS::RR::OPT::DAU); +use parent -norequire, qw(Net::DNS::RR::OPT::DAU); package Net::DNS::RR::OPT::N3U; # RFC6975 -use base qw(Net::DNS::RR::OPT::DAU); +use parent -norequire, qw(Net::DNS::RR::OPT::DAU); package Net::DNS::RR::OPT::CLIENT_SUBNET; # RFC7871
From: rwfranks [...] acm.org
8< Show quoted text
> We have been able to track the bug down to the following: > > 1) Net/DNS/RR/OPT.pm and Net/DNS/DomainName.pm declares several > packages in the same file and is using "use base" to load the parent > class (which is in the same file).
Thanks for your persistence in getting to the root of this problem. Show quoted text
> 2) Our program does daemonize and change its GID/UID to a user which > is not able to read the current working directory.
which we agree is logically unnecessary Show quoted text
> 3) This triggers a side effect of "use base" which will fail as the > current working directory is not readable when requiring > Net::DNS::RR::OPT::DHU which is actually in OPT.pm which has already > been loaded.
Disagree. The problem arises because OPT.pm has *not* been loaded. Arguably, the compiler should recognise the existence of Net::DNS::RR::OPT when it encounters the second package declaration, not when the require is complete. But even if that were fixed tomorrow, we would still need to be compatible with older Perls. Show quoted text
> The fix is to use either a newer version of perl which does not > automatically include the current working directory in the @INC
Would require 5.26.0, which is far too restrictive Show quoted text
> use "use parent -norequire" instead of use base. This is described > here: http://perldoc.perl.org/parent.html
This really amounts to not much more than: our @ISA = qw(Net::DNS::DomainName); but also comes with unwelcome portability concerns: $ echo 'perl -w DomainName.pm ; exit 0' | perlbrew use 5.24.3 A sub-shell is launched with 5.24.3 as the activated perl. Run 'exit' to finish it. Subroutine canonical redefined at /home/rwf/devel/Net/DNS/DomainName.pm line 68. Subroutine decode redefined at /home/rwf/devel/Net/DNS/DomainName.pm line 96. Subroutine encode redefined at /home/rwf/devel/Net/DNS/DomainName.pm line 139. Subroutine _wire redefined at /home/rwf/devel/Net/DNS/DomainName.pm line 146. Subroutine encode redefined at DomainName.pm line 194. Subroutine encode redefined at DomainName.pm line 253. $ echo 'perl -w DomainName.pm ; exit 0' | perlbrew use 5.16.3 A sub-shell is launched with 5.16.3 as the activated perl. Run 'exit' to finish it. Subroutine canonical redefined at /home/rwf/devel/Net/DNS/DomainName.pm line 68. Subroutine decode redefined at /home/rwf/devel/Net/DNS/DomainName.pm line 96. Subroutine encode redefined at /home/rwf/devel/Net/DNS/DomainName.pm line 139. Subroutine _wire redefined at /home/rwf/devel/Net/DNS/DomainName.pm line 146. Subroutine encode redefined at DomainName.pm line 194. Subroutine encode redefined at DomainName.pm line 253. $ echo 'perl -w Mailbox.pm ; exit 0' | perlbrew use 5.8.9 A sub-shell is launched with 5.8.9 as the activated perl. Run 'exit' to finish it. Can't locate parent.pm in @INC (@INC contains: /home/rwf/perl5/lib/perl5/i686-linux /home/rwf/perl5/lib/perl5 /home/rwf/devel /home/rwf/devel/extra/lib /home/rwf/perl5/perlbrew/perls/perl-5.8.9/lib/5.8.9/i686-linux /home/rwf/perl5/perlbrew/perls/perl-5.8.9/lib/5.8.9 /home/rwf/perl5/perlbrew/perls/perl-5.8.9/lib/site_perl/5.8.9/i686-linux /home/rwf/perl5/perlbrew/perls/perl-5.8.9/lib/site_perl/5.8.9 .) at Mailbox.pm line 110. BEGIN failed--compilation aborted at Mailbox.pm line 110.
From: kb [...] open.ch
On Thu Nov 23 12:37:51 2017, rwfranks@acm.org wrote: Show quoted text
>
> > 3) This triggers a side effect of "use base" which will fail as the > > current working directory is not readable when requiring > > Net::DNS::RR::OPT::DHU which is actually in OPT.pm which has already > > been loaded.
> > Disagree. > > The problem arises because OPT.pm has *not* been loaded. Arguably, > the compiler should recognise the existence of Net::DNS::RR::OPT > when it encounters the second package declaration, not when the > require is complete. But even if that were fixed tomorrow, we would > still need to be compatible with older Perls. >
I disagree with your disagreement: The problem arises when loading OPT.pm which contains not only the definition of Net::DNS::RR::OPT, but also for Net::DNS::RR::OPT::DAU which is the parent of Net::DNS::RR::OPT::DHU and Net::DNS::RR::OPT::N3U. What now happens is that "use base" tries to open a DAU.pm. Normally it fails silently if it does not find it, but it explodes if the lookup fails due to missing directory permissions. As this file lookup is not necessary (and is inefficient) there are 3 options to fix it: 1) use "use parent -norequire" instead of use base, but this is not backward compatible 2) use good old @ISA which does exactly what needed, but needs to be guarded by strong comments so that it does not get "modernized" again. 3) Move the definition of Net::DNS::RR::OPT::DAU into a own DAU.pm file
From: rwfranks [...] acm.org
On Fri Nov 24 05:58:57 2017, kb@open.ch wrote: Show quoted text
> I disagree with your disagreement:
I now agree with your disagreement with my disagreement. I was misinterpreting the result of this experiment, which replaces "use base" by its expanded equivalent and warns when invoked: package Net::DNS::DomainName; BEGIN { my $b = qw(Net::DNS::Domain); require base; base->import($b); warn "use base $b;" } . . package Net::DNS::DomainName1035; BEGIN { my $b = qw(Net::DNS::DomainName); require base; base->import($b); warn "use base $b;" } . . package Net::DNS::DomainName2535; BEGIN { my $b = qw(Net::DNS::DomainName); require base; base->import($b); warn "use base $b;" } . . $ perl -w ~/devel/Net/DNS/DomainName.pm use base Net::DNS::Domain; at /home/rwf/devel/Net/DNS/DomainName.pm line 43. use base Net::DNS::Domain; at /home/rwf/devel/Net/DNS/DomainName.pm line 43. Subroutine canonical redefined at /home/rwf/devel/Net/DNS/DomainName.pm line 68. Subroutine decode redefined at /home/rwf/devel/Net/DNS/DomainName.pm line 96. Subroutine encode redefined at /home/rwf/devel/Net/DNS/DomainName.pm line 139. Subroutine _wire redefined at /home/rwf/devel/Net/DNS/DomainName.pm line 146. use base Net::DNS::DomainName; at /home/rwf/devel/Net/DNS/DomainName.pm line 158. use base Net::DNS::DomainName; at /home/rwf/devel/Net/DNS/DomainName.pm line 220. use base Net::DNS::DomainName; at /home/rwf/devel/Net/DNS/DomainName.pm line 158. Subroutine encode redefined at /home/rwf/devel/Net/DNS/DomainName.pm line 193. use base Net::DNS::DomainName; at /home/rwf/devel/Net/DNS/DomainName.pm line 220. Subroutine encode redefined at /home/rwf/devel/Net/DNS/DomainName.pm line 251. 3 options to fix it: Show quoted text
> > 1) use "use parent -norequire" instead of use base, but this is not > backward compatible > 2) use good old @ISA which does exactly what needed, but needs to be > guarded by strong comments so that it does not get "modernized" again. > 3) Move the definition of Net::DNS::RR::OPT::DAU into a own DAU.pm > file
Propose to choose option 2. The Perl code is generated using a macro processor, and there is already a reference to this report in the M4 source.
From: kb [...] open.ch
Nice Show quoted text
> Propose to choose option 2. > The Perl code is generated using a macro processor, and there is > already a reference to this report in the M4 source.
Can we help somehow? Patch?
Fix will be in the upcoming 1.14 release