Feeds:
Posts
Comments

Posts Tagged ‘Annoying Bug’

This is part 4 in my occasional AnyEvent series

When I tried to move my AnyEvent-based code over to Windows today, I got a slightly unpleasant surprise.

$ perl kernel.pl
fcntl is not implemented at c:/strawberry/perl/site/lib/AnyEvent/Util.pm line 362.

(Actually, that path is not accurate – it is from simulating the problem on a different computer. The actual path is a network share.)

Drat I thought, maybe AnyEvent isn’t as portable as I thought. But hang on a minute. When doubting a widely used library ahead of your own code, it is usually your code that is at fault. In my experience anyhow. And besides, Twiggy runs on Windows. What have I done wrong?

So I had a look at the offending line of code.

# Sets the blocking state of the given filehandle (true == nonblocking,
# false == blocking). Uses fcntl on anything sensible and ioctl FIONBIO on
# broken (i.e. windows) platforms.

BEGIN {
   *fh_nonblocking = AnyEvent::WIN32
      ? sub($$) {
          ioctl $_[0], 0x8004667e, pack "L", $_[1]; # FIONBIO
        }
      : sub($$) {
          fcntl $_[0], AnyEvent::F_SETFL, $_[1] ? AnyEvent::O_NONBLOCK : 0;
        }
   ;
}

While I was there, a quick glance down the comments gave me a picture of someone who enjoys working on Windows as much as I do :)

# perl's socketpair emulation fails on many vista machines, because
# vista returns fantasy port numbers.

...

# vista has completely broken peername/sockname that return
# fantasy ports. this combo seems to work, though.

...

# vista example (you can't make this shit up...):

I quickly tracked the root of the problem down to a file called constants.pl. Uh oh, take a look at the WIN32 subroutine.

package AnyEvent;
sub CYGWIN () { 0 }
sub WIN32 () { 0 }
...

That is actually a file generated from a Unix install of AnyEvent. constants.pl is generated at make time from a file called constants.pl.PL that looks like this.

sub i($$) {
   print "sub $_[0] () { ", $_[1]*1, " }\n";
}

print "package AnyEvent;\n";

our $WIN32 = $^O =~ /mswin32/i;

i CYGWIN => $^O =~ /cygwin/i;
i WIN32  => $WIN32;
...

And this is down to my company’s perl policy. A number of pure perl modules are installed on a windows network share which is samba mounted onto the unix servers. We’re primarily a C++/Java shop and Perl is something of a second-class citizen but there are a good number of modules available (including Moose, AnyEvent, POE, etc.)

The downside is that it is hard to get modules installed that aren’t there already, and we are not permitted to download them ourselves. Most of the time, this isn’t a problem.

Anyway, I tried to fix this in my own script using variants on:

package AnyEvent;
use constant WIN32 => 1;
package Kernel;

and

sub AnyEvent::WIN32 () { 1 }

both before and after the use AnyEvent lines. I couldn’t get round it though. This happened when the definitions were after the use lines.

$ perl kernel.pl
Constant subroutine AnyEvent::WIN32 redefined at c:/strawberry/perl/lib/constant.pm line 131.
Constant subroutine AnyEvent::WIN32 redefined at kernel.pl line 23.
fcntl is not implemented at c:/strawberry/perl/site/lib/AnyEvent/Util.pm line 362.

And this is when it was placed before.

$ perl kernel.pl
Constant subroutine WIN32 redefined at c:/strawberry/perl/site/lib/AnyEvent/constants.pl line 3.
fcntl is not implemented at c:/strawberry/perl/site/lib/AnyEvent/Util.pm line 362.

How frustrating!

Read Full Post »

Follow

Get every new post delivered to your Inbox.