Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Backticks within child process

by Anonymous Monk
on Jul 09, 2012 at 16:40 UTC ( [id://980721]=perlquestion: print w/replies, xml ) Need Help??

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

Dear Monks & others,

I don't understand what happens in the script below. Why does the output get jumbled as soon as I remove the comment before my $processes = `ps au`? I would have expected everything inside the child process to run in order, but it looks like the part between the backticks is running asynchronically or something???

for (1..3) { my $fork_pid = fork(); if (! $fork_pid) { print "hello" . "\t"; # my $processes = `ps au`; print "world" . "\n"; exit 0; } }
This is part of a much larger script in which I need to extract some information from 'ps au' to be used in the script.

Replies are listed 'Best First'.
Re: Backticks within child process
by zentara (Archbishop) on Jul 09, 2012 at 16:56 UTC
    It's because you have 3 independent processes all trying to write to STDOUT simultaneously. Try having each fork open a filehandle, and write to it's own file, that should be orderly.

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
Re: Backticks within child process
by onelesd (Pilgrim) on Jul 09, 2012 at 17:03 UTC

    It would help if you pasted your output, and also what you expected to see.

    I suspect you wanted to see something like:

    hello [ps output] world hello [ps output] world hello [ps output] world

    But instead you are seeing something like:

    hello hello hello [ps output] [ps output] [ps output]world world world

    You answered your own question- the 3 forks you did are running async.

Re: Backticks within child process
by sundialsvc4 (Abbot) on Jul 09, 2012 at 17:53 UTC

    Think of “your terminal” as an output file, which in fact it is.   Three processes, all running independently of one another, are simultaneously writing lines of text to that file.   In what order, therefore, will the lines of text appear?   God only knows.

    It would get even more tricky if the character-strings that each process was writing did not end in a newline character.   As it happens, most programming languages buffer character-output such that they only write complete text-lines at a time.   In the worst case, the characters being output by the various competitors could be intermingled.

Re: Backticks within child process
by Anonymous Monk on Jul 09, 2012 at 19:09 UTC

    When the "ps" line is commented out, I see:

    hello	world
    hello	world
    hello	world
    

    When I remove the comment I get

    hello	hello	hello	my@prompt:~$ world
    world
    world
    

    I think I understand it now. I was thrown off by the fact that the "ps" line doesn't do any printing, so I didn't understand how it managed to "jumble" the output. I didn't understand that the time that command takes to run was was important. Thanks for all your input.

      One extra fact: when perl executes the backticks, it flushes the STDOUT buffer: that's why when you include the backticks, the half-lines get flushed to STDOUT, appearing to get jumbled up with half lines from the other processes.

      Dave.

Re: Backticks within child process
by frozenwithjoy (Priest) on Jul 09, 2012 at 16:50 UTC
    What do you mean by "jumbled"? What does it look like?

    Out of curiosity, does your problem go away if you put sleep 1; before your if statement?

Re: Backticks within child process
by The Code Captain (Initiate) on Jul 09, 2012 at 17:49 UTC

    If you don't want to sleep, you could also just collect the output together, rather than printing it in different stages. When you print to a file (and STDOUT is still a file) you are asking perl and the OS to handle the output for you which may not always work in the way you expect. Normally that's not a problem, but if you have different processes all trying to access the same resource (STDOUT for each process is competing for the same terminal session) it probably won't happen quite as you expect.

    So ... you could use something like:

    for (1..3) { my $fork_pid = fork(); if (! $fork_pid) { my ($Output); $Output="hello\t"; $Output.=`ps au`; $Output.="world\n"; print $Output; exit 0; } }

    This keeps the print a single item which is probably going to be written in one go (and hence stay together) as you want. Of course I am sure that your real code is doing something much more interesting than just printing output :o)

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (4)
As of 2024-04-24 03:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found