A concise forking idiom in pure Perl
One of the first module I took over as a maintainer on CPAN was Proc::Fork.
It is a beautiful interface.
It did get a bit uglier in relatively recent times when I added the run_fork
wrapper, an unfortunate necessity in certain cases.
But for small single-file-redistributable programs that can be offered to people who are merely users of a Unix system, who do not have any sort of CPAN setup or installation experience, it always felt like a burden to pull in a dependency for something as… insubstantial as this little bit of syntactic sugar:
run_fork {
child {
# ...
}
parent {
my $kid = shift;
# ...
}
}
Just the other day, it occurred to me that with given
/when
, it is easy to construct an idiom for forking that is just as concise, if not self-documenting to the same extent:
given ( fork ) {
when ( undef ) { die "Couldn't fork: $!\n" }
when ( 0 ) {
# ... child code here ...
}
default {
my $kid = $_;
# ... parent code here ...
}
}
If the code is to run on older perls as well (unfortunately 5.8 is still quite widespread), a less elegant version can be constructed with foreach
:
for ( scalar fork ) {
die "Couldn't fork: $!\n" if not defined;
if ( my $kid = $_ ) {
# ... parent code here ...
}
else {
# ... child code here ...
}
}
[Update: unfortunately, in all perls released to date, fork
in list context returns ()
on failure so it is necessary to spell this scalar fork
, ruining the æsthetic. Sigh.]
While by this point we’ve gone a far cry away from the simple explicitness of the Proc::Fork API, to my mind it is still a lot better than the usual (non-)“idiom” without the outer scope:
my $kid = fork;
die "Couldn't fork: $!\n" if not defined $kid;
if ( $kid ) {
# ... parent code here ...
}
else {
# ... child code here ...
}
This leaves $kid
declared in the outer scope and leaves the flow control scattered below it in the same scope, with nothing holding together the whole thing visually as one unit – to the point where I get a strong Proc::Fork craving to clean away the chaff…
That's a creative use of "given". Looks reasonable to me. Thanks for sharing it.
For Proc::Fork Why not do localise $_ to the first argument?
For fork calls I find 3 functions helpful: