in reply to Re^5: Forking Clients
in thread Forking Clients

Good point, and maybe I am approaching this the wrong way. But here is what I would like to do.

I have a main program, which has a bunch of things it needs to do. From it I want to spawn off a function that will make a call, that function will wait for a response. The main program itself should not wait for it to come back, it should continue on spawning off other functions, or doing basic prints or function calls.

When the spawned off function is done with its work,it would be great if there would be some interrupt which would let me know that it is, if needed I could periodically call a piece of code to check to see if its done.

Does this explain it better?

I really appreciate your help with this.

Replies are listed 'Best First'.
Re^7: Forking Clients
by BrowserUk (Patriarch) on Oct 15, 2008 at 23:04 UTC
    Does this explain it better?

    Kinda. Ignoring how it is implemented for now, let's assume that your functions blah() & blee() etc. are written so that they support the following api:

    my $blah = blah( ... ); my $blee = blee( ... ); ... if( $blah ) { my @blahResults = $blah->(); ... } ... if( $blee ) { my @bleeResults = $blee->(); ... }

    What does your main program look like?


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      The main program is essentially a test script, which communicates via rpc with another server which will execute system commands. There are a bunch of intermediary modules between the main test script and the actual point where the rpc call is made. This is pretty much why I am trying to dumb it down so I understand the basics.

      Here is what I want to do in the main program

      my $remoteServer = new Host($ip); ... #I want the following to run concurrently my @networkinfo = $remoteServer->getNetworkInfo(); my @sysLog = $remoteServer->getSystemLog(); my @scsiInfo = $remoteServer->getScsiInfo(); #So I have kicked all these off, I need to get the #networkinfo and scsiInfo information back before #continuing. The sy +sLog I don't need, its going to be #grabbed way down the line, possibly at the end of the #program ... package Host; sub getNetworkInfo { ($self) = @_; my @results = $self->rpc('RPCService::system_call', 'ipconfig /all' +); return @results; } sub getScsiInfo { ($self) = @_; my @results = $self->rpc('RPCService::system_call', 'scsinit -a'); return @results; } sub getSystemLog { ($self) = @_; my @results = $self->rpc('RPCService::system_call', 'eventlog -a'); return @results; } sub rpc { ($self, $func, $command) = @_; my $ip = $self->getIP(); #start threaded/process code here ..??.. my $port = $self->getPort(); my $connection = ClarRPC->connect($ip, $port); my @resp = $connection->rpc($func, $command); $connection->disconnect(); ..??.. #end threaded/process code here }

      Let me know if I need to clear anything up. Thanks!

        You keep skipping over the important part--the bit above that is just comments--so I'll ask a very specific question.

        You've started all your remote commands--they're running asynchronously. You've done anything else you might want to do before you need the results of the first one--say the getNetworkInfo() in your example--and you are now ready for those results. When you started that command, you got back a handle as I suggested above, and you test the handle to see if the results are ready. What do you do if not?

        What are you going to do in the else clause below?

        my $networkinfo = $remoteServer->getNetworkInfo(); my $sysLog = $remoteServer->getSystemLog(); my $scsiInfo = $remoteServer->getScsiInfo(); ... anything else that needs doing ## Now you're ready for the network info my @networkinfo; if( $networkinfo ) { @networkinfo = $networkinfo->(); } else { ## What would you do here? }

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re^7: Forking Clients
by mr_mischief (Monsignor) on Oct 15, 2008 at 21:05 UTC
    What does the function you spawn off do with the response? Must the main program know what that spawned process has done or that it was successful?

    If you only need to know that the spawned process is complete, then that's pretty easy. A non-blocking wait could help with that if you plan on rolling your own.

    If, however, the main program needs to know what's going on in the spawned processes then you have a more complicated issue.

    I recommend you get and read a book by Stevens. Perhaps UNIX Network Programming, Volume 2, Second Edition: Interprocess Communications, Prentice Hall, 1999 (ISBN 0130810819) or maybe Advanced Programming in the UNIX Environment, Addison-Wesley, 1992 (ISBN 0201563177).

    Before you protest that you're not programming in C or that you're not using Unix, let me point out that the concepts are the same. The Unix family of OSes is the home of sockets, C, Perl, several forms of IPC, regular expressions as a computational tool, and more. Perl borrows heavily from C, Unix, and Unix-borne tools in its concepts. If you know Perl and how IPC works on Unix, then save for a few caveats about other OSes you're mostly set to do IPC in Perl.

      The main program doesn't need to know what the thread is doing in "real-time", just that its done, and when it is, the main program needs to get the results of whatever the thread did. The caveat here is that the main program just needs to be able to do other stuff while the thread is doing its thing.

      I understand how I can spawn the thread/process have it do its thing if there is no need for the main program to get the resultant information back from the thread, but the issue I seem to be having is that I can't get the information back from the thread/process without blocking. I guess I am just not understanding how to implement the non-blocking properly

      Btw, I thank you for the suggestions, I will look at both, the more I know the better.

        If you need the information back at any point, then you have a few options. Sockets, named pipes, temporary files, a data store of some kind (RDBMS, tuple storage, LDAP, etc) or shared memory can work for forked processes. There are lighter-weight ways to pass the data between threads in a multithreaded process.

        If I was to take your original track of forking independent processes and needed the information back asynchronously, I'd probably use TCP sockets or a named pipe. I'd set the parent process up to listen and read without blocking using select and set the children up to connect back to the parent. The child can do what it needs, connect to the parent, dump its report across the socket, then exit. The parent can just ignore child processes exiting with $SIG{'CHLD'} = 'IGNORE';. To know which result is from which child, just have the child include its PID as part of the data it sends in its report. Any child that fails to report back within a certain number of seconds can be sent a kill signal and a new child can take its place in the queue. I think having the parent connect to each child is the wrong way to handle this, because you really only need one socket listening instead of one for each child.