How to launch a wholly independent process on either Unix or Win32 all in same script.

This is part of an XML-RPC Client/Server pair available at the URL below:

XML-RPC Client/Server Pair

# Copyright 2005-09-08 by Gan Uesli Starling
# XML-RPC server reboot script written in Perl.
# 42 liines of code & 30 comment lines.
# For use with this XML-RPC Client/Server pair:
# 1.
# 2.

# On command, the running server reboots itsels as follows:
# 3. Launches this script in manner similar to below.
# 4. Dies when this script kills it.
# 5. Is reborn when new version launched by this script.

# Args sent by the to-be-restarted, still-running server.
my ( $script_path, $script_list, $local_port, 
     $prefork_pid, $plain_pw, $crypt_key ) = @ARGV;

# Lay running server to rest.
kill 15, $prefork_pid; sleep 5; # Gently persuade at first.
kill  2, $prefork_pid; sleep 5; # If ignored, insist harder.
kill  9, $prefork_pid; sleep 5; # If still ignored, use hammer.

# Prepare launch-string for use with 'Process::Create' on Win32.
# Note: Since this is a string, not a list, any scalars which
# are empty may cause problems. Make sure empty any empty 
# scalars are represented by empty double-quotes or else are
# left out entirely, as below.
my $win32_cmd = "wperl $script_path/ "
    . "--script_list $script_list "
    . "--local_port $local_port "
    . "--password $plain_pw "
    . "--gui 0 ";

# On the off chance that key is empty.
$win32_cmd .= "--crypt_key $crypt_key " if $crypt_key;

# Prepare launch-array for use with 'fork' on Unix.
my @unix_cmd = (
    "perl", "$script_path/", 
    "--script_list", "$script_list",
    "--local_port", "$local_port",
    "--crypt_key", "$crypt_key",
    "--password", "$plain_pw",
    "--gui", "0"

# Launch new process the UNIX way.
sub unix_fork_process {
    if ( defined( my $kid = fork ) ) {
        unless ($kid) { 
            exec(@_) or die "Oops! Cannot exec.";

# Launch new process the Win32 way.
sub win32_create_process {
    my $win32_cmd = shift;
    require Win32::Process;
    require Win32;
    no strict;
    my $obj;

    sub ErrorReport{
        print Win32::FormatMessage( Win32::GetLastError() );

        $obj, "C:\\Perl\\bin\\wperl.exe",
        "$win32_cmd", 0, NORMAL_PRIORITY_CLASS, "."
    ) || die ErrorReport();

# Launch new process any way whichever...
if ($^O =~ /Win32/i) { win32_create_process($win32_cmd) }
else { unix_fork_process(@unix_cmd) }
Replies are listed 'Best First'.
Re: Multi-OS Perl fork
by jonadab (Parson) on Sep 06, 2005 at 13:39 UTC

    Are you saying that fork() doesn't work as advertised on Win32? That would be news to me. Or does your Win32 code do something additional that fork() does not do? What? I'm confused; perhaps you could explain?

      I haven't seen any "advertising" for fork() on Win32, but it doesn't work well enough. It seems to work for the people who implemented it, for their exact needs. It cannot work well with sockets and it has problems when running longer processes.

      I've never mustered the strength to track down these problems, but I'm quite sure that they stem from the fact that the fork() emulation is just that, an emulation, and that the parent and forked child are not separated completely. It was easy enough to circumvent this problem in my case, by writing Schedule::Cron::Nofork, but in many other cases, especially test programs, fork() Just Doesn't Work on Win32.

        I haven't seen any "advertising" for fork() on Win32

        By "as advertised", I didn't mean "as advertised specifically for Win32" but more like "as explained in standard documentation, such as the Camel book". I learned Perl from the 2nd ed. Camel while I was still using Windows 95 OSR2, with ActivePerl, and fork *seemed* to work for me, although I never used it extensively.

        It cannot work well with sockets and it has problems when running longer processes.

        Ah. I was not aware of these limitations. I knew that fork didn't work on DOS, but I was not aware that it had issues on Windows.