rapide has asked for the wisdom of the Perl Monks concerning the following question:

I have two processes(A, C) and one thread(B). C wants to print information to streams such as STDERR or STDOUT and A wants to have control over what information that is sent here by reading from these streams constantly. (Important that there are two streams ant not just one)

Basically This is the following pseudo:

A: Fork a new thread B

B: Execute an external process C

B: wait for C to finish, then exit

A: While(STDERR | STDOUT) from C

A: print information.

I've been trying with pipes and shared variables but been unable to make it work. Does anyone have code or perhaps simple code to illustrate this?

Replies are listed 'Best First'.
Re: How to share streams between processes
by Anonymous Monk on Sep 01, 2008 at 09:03 UTC
Re: How to share streams between processes
by zentara (Cardinal) on Sep 01, 2008 at 13:33 UTC
    You can share filehandles between threads, thru the fileno. The following shows one way. You can also fork in a thread( piped-open, IPC::Open3), and pass the fileno back to the main thread thru a shared variable. Then you can read the IPC filehandle in the main thread, with select.
    #!/usr/bin/perl use warnings; use strict; use threads; use threads::shared; # original idea from BrowserUK at # http://perlmonks.org?node_id=493754 for my $file ( map{ glob $_ } @ARGV ) { open my $fh, '<', $file or warn "$file : $!" and next; printf "From main: %s", scalar <$fh> for 1 .. 10; printf "Fileno:%d\n", fileno $fh; threads->create( \&thread, fileno( $fh ) )->detach; printf 'paused:';<STDIN>; } sub thread{ my( $fileno ) = @_; open my $fh, "<&=$fileno" or warn $! and die; printf "%d:%s", threads->self->tid, $_ while defined( $_ = <$fh> ); close $fh; }

    I'm not really a human, but I play one on earth Remember How Lucky You Are
Re: How to share streams between processes
by BrowserUk (Patriarch) on Sep 01, 2008 at 17:55 UTC

    Hm. You want to spawn a thread, execute an external process from within that thread and then leave that thread doing nothing whilst your main thread reads from the process. And once the external process finishes, have the thread terminate.

    Why? Why complicate things by having the thread start the process and then do nothing, if you want the main thread to read the data? Forget the thread, it is achieving nothing but complication. Just run the external process from the main thread in any of the normal ways backticks, piped open IPC::open.


    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.
      Well, the idea is that the external process generates data and the main thread reads this data simultaneously. I might be thinking too complicated when considering an empty thread, but how could I do it?

      Some pseudo to illustrate my point:

      -MAIN: Create new external process
      -----> EXTERNAL: <generates data>
      MAIN: <while data is being generated>
      MAIN: do something with it.
      -----> EXTERNAL: <exits>
      MAIN: <no more data>
      MAIN: <exits>

      Q: If you were to do this with sharing the streams "STDOUT" and "STDERR", how would you?

        If you need the output from both stdout and stderr via a single stream:

        #main my $kid = open my $fh, "theExternalProcess 2>&1 |" or die $!; while( <$fh> ) { ## Read the output from theExternalProcess } ## You'll end up here when the kid goes away

        If you need to keep stdout and stderr separate, then see IPC::Open3 or IPC::Run.


        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.