I’m (unfortunately) doing more work on Windows on these days so I’ve installed a mini Windows-dev environment at home. It is impressive what the libre software guys have done – between Emacs, Cygwin and Perl (and a rusty MinGW C compiler) I feel almost at home.
On Windows, there is an embarrassment of Perl options. I could choose from ActiveState Perl, Strawberry Perl, CygPerl or try and build it myself. I haven’t tried Strawberry Perl so I thought I’d give it a whirl. The install process was pleasant enough but after that I had some problems. I tried my usual perl -MCPAN -e shell incantation followed by installing (upgrading) the CPAN package but it didn’t work. Woe is me!
I reached for old reliable cygperl but that didn’t work either. Hmmm… fishy, I’m sure I haven’t had problems previously. Thankfully googling the exact error lead to a solution which unfortunately I didn’t make a note of. I do remember that it involved a rebase from the static shell, ash. Following that, Strawberry Perl worked too.
The next thing to do was to install POE. POE allows you to structure your code in an event-driven way. I’ve experienced some strange behaviour with POE on various Windows Perl implementations in the past so I want to test a few things.
My basic POE script.
use strict; use warnings; use POE; POE::Session->create( inline_states => { _start => sub { $_[KERNEL]->yield('loop'); }, loop => sub { print "Normal loop\n"; $_[KERNEL]->delay(loop => 1); }, } ); $poe_kernel->run();
That was a cumbersome way to implement a while 1 loop eh?
while (1) { print "Normal Loop\n"; sleep 1; }
The first thing I want to test is timeouts. I actually like the crufty way that timeouts are implemented in perl with eval / sig alarm. I use sleep here to simulate a long running process despite the warning in the documentation.
It is usually a mistake to intermix alarm and sleep calls. (sleep may be internally implemented in your system with alarm)
use strict; use warnings; use POE; sub timeout_test { eval { local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required alarm 3; sleep 5; # This simulates a long-running process alarm 0; }; if ($@) { die unless $@ eq "alarm\n"; # propagate unexpected errors print "Timeout\n"; # timed out } else { # didn't } }
POE sessions are a bit like co-operative threads. If the session doesn’t yield to the kernel, another session can’t run so if the timeout doesn’t work, we won’t see any output after the timeout loop starts.
POE::Session->create(
inline_states => {
_start => sub { $_[KERNEL]->yield('loop'); },
loop => sub {
print "Normal Loop\n";
$_[KERNEL]->delay(loop => 1);
},
}
);
POE::Session->create(
inline_states => {
_start => sub { $_[KERNEL]->yield('loop'); },
loop => sub {
print "Timeout loop\n";
timeout_test();
$_[KERNEL]->delay(loop => 1);
},
}
);
$poe_kernel->run();
Fortunately, it works fine.
$ perl basic-poe.pl Normal Loop Timeout loop Timeout Normal Loop Timeout loop Timeout Normal Loop Terminating on signal SIGINT(2)
Yep. Windows is such a pain for the developer/technical user that’s gotten used to *nix.
I’m on pretty locked down hardware/firewall at work so when I try to do anything like ruby or Perl I can’t get gem/cpan (anything not endorsed by the man) to work.
That being said, I just upgraded my corporate laptop to Windows 7 RC1 Enterprise and it came with MS Powershell 2 CTP3 — that plus EmacsW32 is just about good enough for me.
Hey Jared,
Not really related to this blog entry, but: I like reading your emacs/perl/programming-in-general columns. I wondered if you had any insight into GUI programming in Perl (particularly under Windows).
So far as I can see, there’s Wx, Qt, Tk, and Win32::GUI.
Wx looks halfway decent, but all the docs are written for the C++ programmer and have been poorly translated into Perl (as in, there is documentation for stuff that doesn’t exist in Wx::Perl, and vice-versa).
I haven’t tried Qt.
Tk is ancient and crufty. It works, it’s reasonably well documented, but it looks like crap, especially on Windows. It also doesn’t have some modern Windows UI amenities.
Win32::GUI has okay documentation, with some gaping holes, has some inconsistencies in implementation, has no UI development environment (like Glade for Wx). It’s hard to extend. Also, unlike the others, it works only on Windows.
All of these options seem like a tremendous amount of work for what you get, with steep and confusing learning curves to boot. Most of them have crappy docs, and some of them make crappy UIs. It seems like a total lose, no matter which one you choose.
Do you have any observations or insights (or recommendations)? Thanks.
Hi df,
I have some similar restrictions at work but I can locally install Perl modules. I’m impressed that you’re able to use Windows 7 on your laptop. We’re stuck with XP, not that I think that is a really bad thing mind you.
Hi Sue (nice name by the way
),
As you can probably tell, I’m more of a server guy than a GUI guy although I’ve hacked together a few (ugly) trivial GUIs using Tcl/Tk and WxPython / C++ w/ Wx. If someone asked me to write a GUI on Windows, and gave me a fair bit of flexibility of technology, my choices in rough order of preference would probably be:
Catalyst + JQuery based Web front end
Clojure / Swing (no experience of Clojure yet though)
WxPython (you can program most Perl in Python!)
Emacs-based GUI if appropriate (see for example here)
Wx::Perl
kthx. I appreciate the insight. You have tons of great tips and advice on your blog. Keep it up!
Thanks Sue, I’m blushing here!
Hello, Jared.
I have to ask what you needed to rebase in Strawberry Perl to get it to work?
Let me know – I’d like to do it in the build for the October 2009 versions!
I’m getting different results than you on ActiveState ActivePerl 5.10.
The $SIG{ALRM} code actually runs. But it runs much later than the alarm() call requested.
In the example I whipped up, I had a Perl loop running a few lines of code, the loop reiterates every second, the short of the long being that there are lots of Perl opcodes being executed at the point in time where the alarm should go off, meaning that safe signals should work fine. But they don’t.
Also tried Strawberry Perl 5.10.1.0.beta_1, which exhibits exactly the same bug.
The operating system is Windows 7, which is significant because the alarm() implementation added in ActivePerl 5.8.3 is said to be broken with the new SetTimer() semantics introduced with Windows Server 2003.
(Tried Cygwin Perl too, it died with the usual slew of fork / dll loading errors that cygwin exhibits when you try to do something advanced with it.. Such as installing a CPAN package on a completely blank vanilla installation
)
Experimenting a bit more, I found that things start working in some situations if a call to the core function can_read() in IO::Select is removed.
It seems to me that there is a bug in Perl that causes alarms to be silently cancelled if you do a can_read().
Nasty shit. Takes days to debug. Don’t use signals in Perl.
Ah, and a final note. In your examples where you include a certain number of seconds in alarm() and sleep() calls, it would be helpful if you could include the current time in the debug messages print()ed.
Otherwise it can sometimes be difficult to see from the transcript whether the alarms worked as they should or not.
I am trying to install “HTTP::Server::Brick” and it is stopping with the error … “Your vendor has not defined POSIX macro SIGHUP.”
I’m just beginning to research the issue of signal-definitions in Strawberry. Any links helpful.