http://www.perlmonks.org?node_id=594914

What's your favorite impossible bug? You know, the kind of behavior that defies the obvious logic rules of the universe, like the exception being triggered in the following code:

if ($some_condition) { return $X; } else { return $Y; } die "not reached"; # but see comment below

Often, when these things happen we blame the compiler out of frustration — but in the vast majority of cases, this is unwarranted: we overlooked something, and the behavior is perfectly reasonable (if sometimes quite subtle) when all the facts are adequately considered. The fear of looking like a fool once the Hidden Reason is revealed only makes the revelation harder to achieve :-)

Here's something that's biting me right now; I'm writing up my experience mostly to distract myself from the horror, and also to solicit from you your own "can't happen" sories, as they tend to be pretty amusing... in retrospect.

I'm installing PAR::Packer on a machine, and am getting the error:

is only avaliable with the XS version at /usr/lib/perl5/site_perl/5.8 +.5/Compress/Zlib.pm line 9

This is one of the cases where Carp::croak shows its evil side: the error is actually coming from Scalar::Util, which has this code:

if (grep { /^(dualvar|set_prototype)$/ } @_ ) { require Carp; Carp::croak("$1 is only avaliable with the XS version"); }

Apart from the typo in "available", this code is wrong because it uses $1 not immediately after obtaining it. require Carp is probably overwriting it (it's a global var, after all, overwritten in every capturing regexp), and indeed the error message I was getting (" is only avaliable") can be explained by a failed match or an empty capture.

Impossible #1: I do have the XS version of Scalar::Util installed! But okay, let's hack up the code and get diagnostics. Since this is the system-installed version of the module, I copy it over to /tmp/Scalar/Util.pm and hack that, then rerun make with PERL5LIB pointing at it.

Impossible #2: I don't see my changes! Could I have typoed PERL5LIB? I rerun make, this time with strace, and see that my file actually is being found. Can't be! But it is. Adding a die at the top of the script doesn't change things. Can't be! Putting the die inside a BEGIN block also impossibly doesn't change anything!

Okay, here I am now. To be sure, I'll sleep on this and find the solution — or maybe one of you monks will have found it for me — but for now, I just revel in the phenomenology of this condition. Does gravity still work? Ouch. Yes. Good.




Update: The apparent dishonor of PERL5LIB can probably explained by PAR's myldr, which has taint checks on, at least in part of its flow. But this leaves us with Impossible #3, which is, why does Scalar::Util think it hasn't got the XS stuff available? I installed it myself and saw the c code go in.

Update II: make install in Scalar-List-Utils doesn't seem to work! At least Util.pm is never updated. Edit: no, I must have been on crack.

Update III - resolution: The 2.x line of Compress::Zlib relies on dualvar, but PAR's myldr does something that cannot load dynamic code during build time. Downgrading to version 1.42 has fixed the problem! Hurrah! Am now corresponding with tsee and Paul Marquess to bring this to a close. Wow, this bug that couldn't happen has involved no fewer than three important distributions!