Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Re: question about running a system and a perl function background

by graff (Chancellor)
on Dec 03, 2004 at 02:51 UTC ( [id://412027]=note: print w/replies, xml ) Need Help??


in reply to question about running a system and a perl function background

It sounds like you want to use fork() to launch each of the four processes -- something like this (untested): update: Based on ikegami's more knowledgeable reply, the following is the sort of thing you'd do if you weren't using Windows; but if you replace the fork stuff with your original "system 1,...", I think the while loop using "wait" will still do what you want.
my %children; for my $n ( 1..4 ) { my $child = fork; if ( !defined $child) { die "fork failed on $n: $!" } elsif ( $child == 0 ) { # this is what the child does: exec 'some', 'process', $n; } $children{$child} = $n; } while ( keys %children ) { my $reaped_pid = wait; if ( exists( $children{$reaped_pid} )) { checkerror_function( $children{$reaped_pid} ); delete $children{$reaped_pid}; } else { # if you get here, better study "perldoc perlipc" } }
I would assume that the "checkerror" function needs to know which of the sub-processes has just finished, so that it knows which set of output to check. That's why I kept track of the loop counter when forking, and pass it to checkerror_function when reaping.

(update: fixed missing close-quote and added slight improvement to "die" message)

  • Comment on Re: question about running a system and a perl function background
  • Download Code

Replies are listed 'Best First'.
Re^2: question about running a system and a perl function background
by ikegami (Patriarch) on Dec 03, 2004 at 06:20 UTC
    system 1, is Windows specific fork+exec that works better than fork+exec on Windows. By switching to fork+exec, you've taken a step backwards. system 1, returns the child's pid, so I think your solution could be rewritten to use system 1,.
      system 1, is Windows specific fork+exec that works better than fork+exec on Windows.
      Ah. I was actually wondering about that -- I had never seen "system 1," before and wasn't even sure whether it was a mistake. (I'm blissfully ignorant of most of the Windows-specific extensions to Perl.) Thanks.
      Hello,

      Is  system 1, supposed to return the child's pid? It seems to return -1 when I tested it out. Is there any other windows command that might return the child's pid?

      Thanks for the response.

        The "piped open" (See perlopentut) returns the pid of the child process.

        See also Re^5: question about running a system and a perl function background in this thread for an example of use.


        Examine what is said, not who speaks.        The end of an era!
        "But you should never overestimate the ingenuity of the sceptics to come up with a counter-argument." -Myles Allen
        "Think for yourself!" - Abigail        "Time is a poor substitute for thought"--theorbtwo         "Efficiency is intelligent laziness." -David Dunham
        "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon

        I believe it should. Have you tried printing "$!" and/or "$^E"? They may give you a meaning the cause of the error.

Re^2: question about running a system and a perl function background
by Anonymous Monk on Jan 07, 2005 at 14:08 UTC
    Hello graff,

    I have been attempting to do the same thing using threads according to BrowserUK's solution. But due to some complicated issues with the system I am using, I am trying to attempt the same thing using fork and exec instead.

    Is it possible to have some arrangement whereby the original process sets up a separate STDOUT/STDIN prior to forking each command and then uses select to read the output from the child processes back into the parent for further possessing?

    BrowserUK also is interested in seeing a working example using fork and exec.

    So after the process forks, can I read each line that the process outputs, see if that line contains a search word I am looking for and if it does, stop all other forks immediately.

    So for example if I am forking three processes: Dir C:, Dir I:, Dir P: Then if any of those contain the searchword “Desktop”, then I would li +ke to immediately stop all the other forks.

    If you could provide a working example, me and BrowserUK would learn a lot.

    Thank you.

      If I understand right, you want a form of IPC such that some number of processes can run in parallel, and as soon as any one of them comes up with "the answer", that job and all the others should immediately stop, and the parent should proceed to do stuff with the answer.

      In this sort of case, playing with the stdin/stdout of all the children, and making the parent read all output from all children, strikes me as being more complicated than necessary (unless there's really something in your setup that makes it essential for the parent to see/process all the input from all children, and/or makes it impossible for the children to write to a commonly accessible disk).

      Anyway, if you're actually just talking about a case where a few children need to run the same sort of search in parallel to cover a few different spaces, just set up the children so that each one will write whatever information the parent needs into a file. The parent should set the file name in advance (one that does not exist), and pass it along to all the children; then, after starting the kids going, it should just loop, watching for the file to come into existence. As soon as the file is there, "bye-bye, kids!"

      If there's any chance of a race condition among children (i.e. two or more could come up with "the answer"), and especially if writing the file is more than just "open, write a record, close", it will probably be best for each child to write to its own personal temp file; once that file is complete and closed, check for existence of the parent's designated file, and if it does not exist, rename the temp file to the designated file name.

      If the child processes involve something like "dir" or "find", i.e. some general-purpose tool that doesn't provide a way to stop as soon as some special condition is met, you could write a wrapper script to serve as the child process for the fork/exec; the child wrapper just needs to do a pipeline open of the general-purpose tool, and do the right thing when the target output shows up (closing the pipe file handle stops the tool).

      (Sorry about not providing a working example, but I hope it's simple enough to work out on your own.)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://412027]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (3)
As of 2025-05-19 15:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?
    erzuuliAnonymous Monks are no longer allowed to use Super Search, due to an excessive use of this resource by robots.