Feeds:
Posts
Comments

Posts Tagged ‘windows perl’

Having had a couple of surprising experiences with third-party perl modules using signals on windows, I decided to test them to see how extensive support is. As mst points out, it is good to have confidence in your chosen platform.

Here is my test program.

#!/usr/bin/env perl

use 5.010;

use strict;
use warnings;

say '#', scalar(keys %SIG), ' signals';

my %skip = map { $_, 1 } qw(STOP TSTP TTIN TTOU);

foreach my $sig (sort keys %SIG) {
    next if (exists $skip{$sig});

    my $pid = fork();
    if (! $pid) {
        sleep 1;
        say "$sig failed!";
        exit 0;
    }

    say "Testing $sig (on $pid)";
    kill $sig, $pid;
    my $catch = wait();
    say "($sig) $catch exited...\n";
}

I fork a new process (presumably this is a pseudo-fork piggy-backing on a thread instead of a process in windows, but it is something people might write if they weren’t aiming at portability to windows), and then I try and send it a signal using kill. If the kill fails, then we get a message.

On Linux, this works pretty well as you would expect, signalling both from the parent and from within the child (suiciding?). A few signals unsurprisingly didn’t cause the child to abort: CHLD, CLD, CONT, FPE, NUM32, URG, WINCH and a few needed to be skipped. However, it was consistent from run to run.

The tests on Windows varied from run to run. The first run aborted on the first signal (SIGABRT appropriately enough).

jared@win32 $ ./signal-test.pl
#26 signals
Testing ABRT (on -3628)
Terminating on signal SIGABRT(22)

The next one ran through to SIGFPE.

jared@win32 $ ./tsig2.pl
#26 signals
Testing ABRT (on -268)
ABRT failed!
(ABRT) -268 exited...

Testing ALRM (on -1440)
ALRM failed!
(ALRM) -1440 exited...

Testing BREAK (on -2596)
BREAK failed!
(BREAK) -2596 exited...

Testing CLD (on -3464)
CLD failed!
(CLD) -3464 exited...

Testing CONT (on -2360)
CONT failed!
(CONT) -2360 exited...

Testing FPE (on -3508)
Terminating on signal SIGFPE(8)

And the third ran through to SIGBREAK.

jared@win32 $ ./tsig2.pl
#26 signals
Testing ABRT
ABRT failed!
(ABRT) -3548 exited...

Testing ALRM
ALRM failed!
(ALRM) -2800 exited...

Testing BREAK
Terminating on signal SIGBREAK(21)

*sigh*. Well, that is pretty disappointing. I had a bunch of other signal related tests I was thinking about doing but there seems little point. I always think of Perl as a fairly platform-agnostic wrapper around the underlying OS, but it looks like I was seriously mistaken.

Read Full Post »

Okay, so down to business. One thing I like about straight cgi vs mod_perl is that any changes are immediately reflected on page refresh. And plackup (and twiggy) both offer an option to auto-restart when files change. Sounds good.

jared@win32 $ plackup -h
...
-r, --reload
        Make plackup to watch updates from your development directory and
        restarts the server whenever a file is updated. This option by
        default watches the "lib" directory and the base directory where
        *.psgi* file is located. Use "-R" if you want to watch other
        directories.
...
jared@win32 $ twiggy -r --listen :8080 hello.psgi
Watching ./lib hello.psgi for file updates.
./lib: No such file or directory at c:/strawberry/perl/site/lib/Filesys/Notify/Simple.pm line 156
Terminating on signal SIGINT(2)

Hmmm… I didn’t ask it to watch ./lib (and it doesn’t acknowledge changes to hello.psgi). Let me change the watched files with -R.

jared@win32 $ plackup -r -R hello.psgi --listen :8080 hello.psgi
HTTP::Server::PSGI: Accepting connections at http://0:8080/
Watching hello.psgi ./lib hello.psgi for file updates.
./lib: No such file or directory at c:/strawberry/perl/site/lib/Filesys/Notify/Simple.pm line 156
Terminating on signal SIGINT(2)

Er, okay, -R only allows you to add paths. So there is not an obvious way of removing the paths that already exist. *sigh*. I submit to the inevitable.

jared@win32 $ mkdir lib
jared@win32 $ twiggy -r --listen :8080 hello.psgi
Watching ./lib hello.psgi for file updates.

So I make a change to hello.psgi and get the following:

-- C:\home\jared\plack-tests\hello.psgi updated.
Killing the existing server (pid:-2872)

Almost! But I’m missing the message that says it was able to restart the server.

waitpid($pid, 0);
warn "Successfully killed! Restarting the new server process.\n";

In actual fact, the process it claims it has killed is still running and I’m still able to connect to it. So I hack Restarter.pm a bit (more on that at the end).

jared@win32 $ twiggy -r --listen :8080 hello.psgi
Watching ./lib hello.psgi for file updates.
-- C:\home\jared\plack-tests\hello.psgi updated.
Killing the existing server (pid:-2156)
Successfully killed! Restarting the new server process.
bind: Unknown error at c:/strawberry/perl/site/lib/Twiggy/Server.pm line 71
    -L, --loader

Using plackup instead of twiggy works.

jared@win32 $ plackup -r --listen :8080 hello.psgi
HTTP::Server::PSGI: Accepting connections at http://0:8080/
Watching ./lib hello.psgi for file updates.
-- C:\home\jared\plack-tests\hello.psgi updated.
Killing the existing server (pid:-3544)
Successfully killed! Restarting the new server process.
HTTP::Server::PSGI: Accepting connections at http://0:8080/

Although having thought about it, maybe the Shotgun loader is what I really want.

jared@win32 $ twiggy --listen :8080 hello.psgi -L Shotgun
Attempt to free unreferenced scalar: SV 0x2c78b04,
Perl interpreter: 0x2400054 at
c:/strawberry/perl/site/lib/Plack/Loader/Shotgun.pm line 48.

Again, plackup works here where twiggy does not.

jared@win32 $ plackup --listen :8080 hello.psgi -L Shotgun
HTTP::Server::PSGI: Accepting connections at http://0:8080/
127.0.0.1 - - [22/Mar/2010 21:21:31] "GET / HTTP/1.1" 200 42 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.9.2) Gecko/20100115 Firefox/3.6 (.NET CLR 3.5.30729)"
127.0.0.1 - - [22/Mar/2010 21:21:35] "GET /favicon.ico HTTP/1.1" 200 42 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.9.2) Gecko/20100115 Firefox/3.6 (.NET CLR 3.5.30729)"
127.0.0.1 - - [22/Mar/2010 21:22:07] "GET / HTTP/1.1" 200 42 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.9.2) Gecko/20100115 Firefox/3.6 (.NET CLR 3.5.30729)"

# –

And at the risk of getting pointed comments for using the KILL signal, here is the hack I made to Restarter.pm. (Hey, what can I do? My OS blows.)

--- Plack.orig/Loader/Restarter.pm      2010-03-22 20:50:16 +0000
+++ Plack/Loader/Restarter.pm   2010-03-22 21:31:06 +0000
@@ -37,6 +37,12 @@
     my $pid = $self->{pid} or return;
     warn "Killing the existing server (pid:$pid)\n";
     kill 'TERM' => $pid;
+
+    if (lc($^O) =~ /mswin32/) {
+        sleep 1;
+        kill 'KILL' => $pid;
+    }
+
     waitpid($pid, 0);
     warn "Successfully killed! Restarting the new server process.\n";
 }

Read Full Post »

Now I have my command prompt set up the way I like it, installing modules into strawberry perl from from cpan is easy. Okay, fine, it was easy before, but now I just need to run my batch file and type cpan.

Okay, so one of the things I’m interested in is running Plack on Windows. And Twiggy looks like the obvious choice for HTTP servers supporting PSGI – the benchmarks I looked at state it is the second most performant pure(ish)-perl option after Starman and Starman clearly states it isn’t supported on Windows. Does the fact that Twiggy doesn’t say that mean that it works?

c:\home\jared>cpan

cpan shell -- CPAN exploration and modules installation (v1.9452)
Enter 'h' for help.


cpan> install Plack::Handler::Twiggy

...

t/02_signals.t .......... skipped: Broken perl detected,
skipping tests.
t/03_child.t ............ skipped: Your perl interpreter
is badly BROKEN. Child watchers will not work, ever. Try
upgrading to a newer perl or a working perl (cygwin's perl
is known to work). If that is not an option, you should be
able to use the remaining functionality of AnyEvent, but
child watchers WILL NOT WORK.

...

Yikes! This was emitted when building AnyEvent (a pretty key part of Twiggy). It doesn’t sound good does it? It comes from the following test:

BEGIN {
   # check for broken perls
   if ($^O =~ /mswin32/i) {
      my $ok;
      local $SIG{CHLD} = sub { $ok = 1 };
      kill 'CHLD', 0;

      unless ($ok) {
         print <<EOF;
1..0 # SKIP Your perl interpreter is badly BROKEN. Child watchers will not work, ever. Try upgrading to a newer perl or a working perl (cygwin's perl is known to work). If that is not an option, you should be able to use the remaining functionality of AnyEvent, but child watchers WILL NOT WORK.
EOF
         exit 0;
      }
   }
}

Okay, so child watchers don’t work (whatever they are). Hopefully Twiggy doesn’t need ‘em. Let’s plough on regardless. This is the standard Hello World app.

my $app = sub {
    my $env = shift;
    return [
        200,
        ['Content-Type' => 'text/plain'],
        [ "Hello stranger from $env->{REMOTE_ADDR}!"],
    ];
};

And firing up twiggy works, at least for this simple example.

jared@win32 $ twiggy --listen :8080 hello.psgi

Read Full Post »

Follow

Get every new post delivered to your Inbox.