Subject: | Net::LDAP bug: CAN_IPV6 vs. $SIG{__DIE__} |
Date: | Thu, 6 Nov 2014 10:05:47 -0600 |
To: | <bug-perl-ldap [...] rt.cpan.org> |
From: | Troy Loveday <troyl [...] ti.com> |
My host is
$ uname -a
Linux onepgrts.dal.design.ti.com 3.0.101-0.7.17-default #1 SMP Tue Feb 4 13:24:49 UTC 2014 (90aac76) x86_64 x86_64 x86_64 GNU/Linux
I am running Perl 5.14.2
$ perl -v | head -1
This is perl 5, version 14, subversion 2 (v5.14.2) built for x86_64-linux-thread-multi
I am using Net::LDAP 0.57
$ perl -MNet::LDAP -e 'print "$_\n" for $Net::LDAP::VERSION;'
0.57
(HOWEVER, the code and proposed fix below are for the current 0.64 version.)
In the case where any one of the IPv6 modules is not present, the
following line of code from Net::IPV6 0.64 can trigger a $SIG{__DIE__}
handler that is assigned within a BEGIN block, before doing "use
Net::LDAP":
use constant CAN_IPV6 => eval { require IO::Socket::IP; IO::Socket::IP->VERSION(0.20); }
? 'IO::Socket::IP'
: eval { require IO::Socket::INET6; }
? 'IO::Socket::INET6'
: '';
The problem is explained in 'perldoc -f eval':
Using the "eval{}" form as an exception trap in libraries does have some issues. Due to
the current arguably broken state of "__DIE__" hooks, you may wish not to trigger any
"__DIE__" hooks that user code may have installed. You can use the "local $SIG{__DIE__}"
construct for this purpose, as this example shows:
# a private exception trap for divide-by-zero
eval { local $SIG{'__DIE__'}; $answer = $a / $b; };
warn $@ if $@;
And also in 'perldoc perlvar':
Due to an implementation glitch, the $SIG{__DIE__} hook is called even inside an "eval()".
The fix is to change the above line in Net::LDAP to localize $SIG{__DIE__}:
use constant CAN_IPV6 => do {
local $SIG{__DIE__};
eval { require IO::Socket::IP; IO::Socket::IP->VERSION(0.20); }
? 'IO::Socket::IP'
: eval { require IO::Socket::INET6; }
? 'IO::Socket::INET6'
: '';
};
(The attached diff can be used to patch the current 0.64 version of LDAP.pm.)
The following perl command will demonstrates the problem (but only in
the case where any one of the IPv6 modules is not present):
$ perl -Mstrict -Mwarnings \
-e 'BEGIN { $SIG{__DIE__} = sub { print "__DIE__ handler: @_\n"; }; } use Net::LDAP;'
__DIE__ handler: Can't locate IO/Socket/INET6.pm in @INC (@INC contains: /apps/perl/5.14.2/lib/site_perl/5.14.2/x86_64-linux-thread-multi /apps/perl/5.14.2/lib/site_perl/5.14.2 /apps/perl/5.14.2/lib/5.14.2/x86_64-linux-thread-multi /apps/perl/5.14.2/lib/5.14.2 .) at /apps/perl/5.14.2/lib/5.14.2/Net/LDAP.pm line 31, <DATA> line 749.
I hope I have provided enough details to clearly explain and demonstrate the problem.
--
Troy Loveday e-mail: <troyl@ti.com>
External Development & Manufacturing phone: 214-567-6463
Texas Instruments, Inc.
Dallas, Texas
Message body is not shown because sender requested not to inline it.