Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Perl Background processes in Windows

by spx2 (Chaplain)
on Jan 18, 2008 at 16:15 UTC ( #663081=perlquestion: print w/ replies, xml ) Need Help??
spx2 has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I am building an application in Linux and starting
background processes like this system("perl stuff.pl &").
I am thinking about porting all of it to Windows.
Does Windows have this option of launching processes in background.
How would you do this ?
Thank you

Comment on Perl Background processes in Windows
Download Code
Re: Perl Background processes in Windows
by BrowserUk (Pope) on Jan 18, 2008 at 16:21 UTC
Re: Perl Background processes in Windows
by RainmanPM (Novice) on Jan 18, 2008 at 19:51 UTC
    I use the Win32::Process module, which allows a bit more control.
Re: Perl Background processes in Windows
by mpeg4codec (Pilgrim) on Jan 18, 2008 at 22:46 UTC
    The most portable way of doing this that I can think of is to use fork followed by exec. Consider the following:
    sub run_in_bg { my $pid = fork; die "Can't fork a new process" unless defined $pid; # child gets PID 0 if ($pid == 0) { exec(@_) || die "Can't exec $_[0]"; } # in case you wanted to use waitpid on it return $pid; }
    You'd call this the same way you'd call system, except now it forks a new process before running the first arg.
      Be careful with that solution. Fork on windows is emulated using threads, not real processes. See perlfork doc. This may not matter for your application, but you should be aware of it.
Re: Perl Background processes in Windows
by peterdragon (Beadle) on Jan 20, 2008 at 13:02 UTC
    Here's a demo program showing how to write a cross-platform Windows/Linux background process spawner
    #!/usr/bin/perl
    
    use warnings;
    use strict;
    
    use Carp;
    use Time::HiRes;
    use POSIX 'setsid';
    
    my $child_pid;
    my $child_proc;
    my $cmd = "./aprogram.exe";
    my $debug = 1;
    
    start_child();
    sleep(5.0);
    stop_child();
    
    sub start_child
    {
      die "cannot execute cmd: $cmd" unless -x $cmd;
      if ($^O eq 'MSWin32') # Windows
      {
        require Win32::Process;
        Win32::Process::Create($child_proc, $cmd, $cmd, 0, 0, ".") || confess "Could not spawn child: $!";
        $child_pid = $child_proc->GetProcessID();
      }
      else # Unix
      {
        $SIG{CHLD} = 'IGNORE';
        $child_pid = fork();
        unless (defined $child_pid)
        {
          confess "Could not spawn child (Unix): $!";
        }
        if ($child_pid == 0 ) # child
        {
          unless ($debug)
          {
             open STDIN, "<", "/dev/null"   or die "Can't read /dev/null: $!";
             open STDOUT, ">", "/dev/null"  or die "Can't write /dev/null: $!";
          }
          setsid or warn "setsid cannot start a new session: $!";
          unless ($debug)
          {
             open STDERR, '>&STDOUT'  or die "Can't dup stdout: $!";
          }
          local $| = 1;
          unless (exec($cmd))
          {
            confess "Could not start child: $cmd: $!";
            CORE::exit(0);
          }
        }
        # parent
        $SIG{CHLD} = 'DEFAULT';
      }
      # catch early child exit, e.g. if program path is incorrect
      sleep(1.0);
      POSIX::waitpid(-1, POSIX::WNOHANG()); # clean up any defunct child process
      if (kill(0,$child_pid))
      {
        print "Started child process id $child_pid\n";
      }
      else
      {
        warn "Child process exited quickly: $cmd: process $child_pid";
      }
    }
    
    sub stop_child
    {
        if ($^O eq 'MSWin32') # Windows
        {
          Win32::Process::KillProcess($child_pid,0);
        }
        else # Unix
        {
          kill 9, $child_pid || warn "could not kill process $child_pid: $!";
        }
        print "Stopped child process id $child_pid\n";
    }
    
      @ Peter Dragon, Did you ever test your script? It can never work as the script starts with a die........

        @ Peter Dragon, Did you ever test your script? It can never work as the script starts with a die........

        A conditional die, makes all the difference in the world

        $ perl -le " die 6 if 9 " 6 at -e line 1. $ perl -le " die 6 if not 9 ; die 8 " 8 at -e line 1.
Re: Perl Background processes in Windows
by temporal (Pilgrim) on Mar 27, 2012 at 16:05 UTC

    I recently had to write a quick script that I wanted to run in the background indefinitely in Windows.

    Tried to find a solution with Win32::Process, but whenever I killed the parent process the child would die as well.

    Anyway, I went ahead and ended up doing this:

    fork() ? exit(): exec("$cmd $args");

    I know Windows implements fork differently which probably explains an odd bug where the parent process hangs instead of exiting. This is fine, I kill it manually. The end result - a headless, background child process - still works fine.

    Annoying side effect of Perl's fork() implementation on Windows, the PID is not valid. So I cannot keep track of it to kill the process later.

    Actually, I'm a little baffled that this method works. Isn't Perl fork() on Windows supposed to simulate another process, not actually create another one? I believe it has something to do with the nature of exec().

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://663081]
Approved by Corion
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (3)
As of 2014-10-26 07:41 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (152 votes), past polls