Greetings ... I am writing a daemon utility which forks off a child, that may execute fairly arbitrary code (defined by a series of external files which get eval'd in), which given the nature of the daemon to initate build requests, will most likely include many calls to system(), thus creating dubious sub-children, whose output I'd like to catch using the same pipe, ideally ... but the problem is that their output doesn't get caught by my pipe call.

So ... the execute subroutine goes something like so:



# ... in another init subroutine, the external files get eval'd in,
# defining code references and data structures, in preparation
# for this task_exec subroutine ...

sub task_exec {
   # ... perform pre-init ... 

   if($pid = fork){
       # ... parent: save $pid in a hash record ...
   } else {

       # first child, set up pipes:

       pipe(CHILD_RDR, PARENT_WTR);
       CHILD_RDR->autoflush(1);
       PARENT_WTR->autoflush(1);

       if($fpid = fork()){
           select(PARENT_WTR);
           open(STDERR, ">&PARENT_WTR"); # merge STDOUT with STDERR

           # execute a list of code references, defined in a global structure:
           foreach $step (@{$TasksByName{$p{task}{steps}}}){
               chdir($p{sandbox});

               # execute the actual step code, some sequences might
               # go something like system("./configure") or "make"

               if(&$step( ... pass some stuff ... ) != 0){
                    print STDERR "something bad happened!\n";
                    exit(1);
               }
           }

           kill 'INT' => $fpid;  # sent interrupt to child reader
           waitpid($fpid, 0);

           exit(0);
       } else {
           # child reader, essentially acts like the "tee" program
           
           $fdout = new IO::File("> $p{sandbox}/task.out");
           if(!$fdout){
               die "can't open output file: $!";
           }

           $SIG{INT} = sub {
                      print STDERR "caught SIGINT, exiting!\n";
                      close(CHILD_RDR);
                      $fdout->close();
                      exit(0);
           };

           while(defined($l=<CHILD_RDR>)){
                print $fdout $l;
           }
           exit(0);
       }
       exit(0); # first child
   }
}

So, what's happening is that the contents of &$step(...) subroutines in turn call various commands via system(...), the output of which I would like to catch in my pipe call, which is currently not happening. The contents of &$step is defined in a series of external files that get eval'd in at init time, which also define pretty sophisticated structured data to be communicated to the server, which is why I chose this eval-centric approach in the first place (as opposed to doing something like system("task-script.pl > task.out").

What does your wisdom dictate that I should do? (And hopefully I'm explaining my predicament clearly enough.)


In reply to Collecting STDOUT from childeren (and subchilderen) via pipe() by johnc909

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.