Sometimes Perl just seems broken
Hey, call me crazy, but I was thinking that I could hack something
together to check that a package implements all the functions in
another package. I called these “interfaces”; you may remember my
interface.pm.
Well, today I find that if a package that has use interface is
itself use‘d from inside an eval block, the CHECK block
that interface.pm sets up creates that Too late to run CHECK
block message or whatever it was (see last entry). Joy.
I thought up two or three ways to fix this. First I thought, “OK,
I’ll just undef the package namespace, remove it from %INC,
then reload the fucking thing manually and slap a CHECK in before
interface.pm’s eval is done.” After reading that, I think
this is a more appropriate description of what I was intending:
undefcaller’s name space.Profit.
undef a name space (undef %{ "SomePackage::" }).
This seems to make Perl act weirdly, like apparently corrupting
strings (including code it’s reading in, I think) and sometimes you
get SIGSEGV. Needless to say the above was a failure.
So then I decide I’ll just force loading of the package with
require (after deleting the package from %INC of course), run
the function that checks for proper implementation of an interface,
and then undef everything that I just loaded so when my import
function returns you won’t get a bunch of “redefined” warnings. This
method worked for my simple test, but quickly revealed two problems
with a more complex test. First, in the process of undef‘ing
everything, I undef‘ed some stuff that was imported from other
modules. I can’t think of any way around this, except maybe requiring
use interface to be before any other imports. Secondly, and most
obviously, you’d be loading the fucking file twice. God help you
if it’s something like a big Parse::RecDescent parser or something.
I also need to restore the entry to %INC when I’m done with my
undefining, otherwise the file will get reloaded later, producing
those “redefined” warnings we were trying to avoid earlier. Problems
aside, the first of which I think is impossible to fix, this is the
most successful method yet.
The third thing I tried was just creating a CHECK method in the
caller. I.e.: *Caller::CHECK = sub { ... }. This didn’t work;
as near as I could tell the CHECK method never got ran. It might
work if the caller first defined a CHECK block (save the caller’s
CHECK, replace the symbol table entry in the caller’s package with
our own CHECK routine) but that would be a silly requirement.
So, any Perl wizards have a suggestion? (Other than, “that’s not the Perl way; stop trying to guarantee interfaces” or something like that.) Please mail me.
In other news I got Icecast 2 working, along
with darkice for streaming to the server from my line in. quality =
0.5 in darkice seemed to fill up my upstream pretty nicely. People
were semi-frequently (ranging between 2m and 15m) getting disconnected
from the server for no apparent reason. The server seemed to be
sending the FINs too. Nothing in the logs about it. Still, I was
able to spin and others were apparently able to hear me. With a
little more bandwidth and a bit more ambition, maybe I could get my
USB web cam to stream me spinning too. It’s real exciting to see a
guy standing in front of some turntables for an hour, BTW. Trust me.