darkness

Tuesday, 31 December 2002

Sometimes Perl just seems broken

darkness @ 05:01:03

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:

  1. undef caller’s name space.

  2. Profit.

I will take this opportunity to inject a bit of wisdom into the world: don’t 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.

No Comments »

No comments yet.

RSS feed for comments on this post. TrackBack URL

Leave a comment

Powered by WordPress