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

strange behaviour when forking lots of times

by jesuashok (Curate)
on May 16, 2006 at 03:38 UTC ( [id://549655]=perlquestion: print w/replies, xml ) Need Help??

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

hi all

These days I am learning perl by writing simple perl programs. I have done lot of system side programing using fork in 'C' language. So I have enough knowledge on fork and its behaviour.
I am wondering the behaviour of fork, when I use it with perl. I might have not understood the fork concepts properly in perl.
definitely monks can explain me better. Here is my code

fork || print for split (//, "a" x 10);
Output :-
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaa aaaaaaaaa1a11aaa1aaa1aaa11a1aaaaaa111a1a11a11a1a111aaa1aaaaaaaaaaaaaaa +aaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaa aaaaaaaaaaaaaaaaaa1aaa1a1a1aaaaaaaaaaaa11aaaaaa1a111a1a1a1aaa11aa1a11a +111a111aaa 1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1aa1a1a1111a111aaaaaaaaaa11aaaaaaaaaa +a11111a1aa a1aaaaaaaaaaaaaaaaaaaaaa1a11111aaaaaaaaaaaaaaaaaaaaaaaaaaa11aaaaaaaaaa +aaaaaaaaaa aaaaaaaaaaa
Output prints some '1's in between 'a'.
could anyone explain me what is happening with the code ?

"Keep pouring your ideas"

Replies are listed 'Best First'.
Re: strange behaviour when forking lots of times
by Zaxo (Archbishop) on May 16, 2006 at 04:57 UTC

    Caution when experimenting with this. It's a very effective fork bomb for slightly larger values of 10.

    Perl fork behaves exactly like unistd.h fork(), except that the return value differs on failure. When fork fails, it returns undef instead of -1, as C fork() does.

    Here's my forking idiom:

    my %kid; { defined(my $cpid = fork) or warn $! and last; $cpid and $kid{$cpid} = undef, last; undef %kid; # in child now # do childish things exit 0; } # . . . delete $kid{wait()} while %kid;
    There are other ways to avoid zombie kids. Which you choose depends on how your program flow is intended to go.

    After Compline,
    Zaxo

Re: strange behaviour when forking lots of times
by davido (Cardinal) on May 16, 2006 at 05:22 UTC

    What you are learning with this simple Perl program is that if you fork 10! (ten factorial) times, and you're lucky enough for your system to still be running, you get odd behavior. For the record, 10! (ten factorial) means you're spawning a total of 3628800 child processes (three million, six hundred twenty eight thousand, eight hundred).

    The immediate lesson learned should be "Don't do that." And the "big picture" lesson learned should be "Be careful when using fork, that you don't unwittingly create a fork bomb."

    The disasterous magic here is that each forked process inherits the remainder of the loop. So ten processes are spawned, each of whom spawn nine processes, each of whom spawn eight, and each of those spawn seven... and so on.

    10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 = 10! = 3628800. Wow!


    Dave

      No, it forks about 2**11 processes. The first time through the loop, it forks once, creating two processes that each have 9 items left to do. The next time, the 2 processes become 4 that each have 8 items left to do. Then 4 become 8 that each have 7 items left to do... For a total of 2*(2**$N-1). And the whole run takes a fraction of second. (:

      - tye        

Re: strange behaviour when forking lots of times
by spiritway (Vicar) on May 16, 2006 at 04:23 UTC

    It looks like you're running into some sort of resource limit and getting strange results. The perlfork doc says:

    In the eyes of the operating system, pseudo-processes created via the fork() emulation are simply threads in the same process. This means that any process-level limits imposed by the operating system apply to all pseudo-processes taken together. This includes any limits imposed by the operating system on the number of open file, directory and socket handles, limits on disk space usage, limits on memory size, limits on CPU utilization etc.

      When I run
      perl -e 'fork || print for split (//, "a" x 10);'
      I get only 'a's not a single 1. Its Fedora core-3 with v5.8.5 of Perl

      It's important to note that perlfork discusses fork emulation, which is only relevant on Windows.

      -nuffin
      zz zZ Z Z #!perl
Re: strange behaviour when forking lots of times (Win32)
by tye (Sage) on May 16, 2006 at 15:08 UTC

    Since I can reproduce this on Win32, I'll bet you were doing it on Win32 as well and that the "1"s can be explained by the fact that Perl's fork emulation on Win32 is pretty seriously broken any time I've even tried to do trivial things with it. Emulating fork isn't simple and, as you can see, it is still pretty easy to get Perl do bizarre things because you used fork on Win32.

    - tye        

Re: strange behaviour when forking lots of times
by kvale (Monsignor) on May 16, 2006 at 04:25 UTC
    When I run the code on my linux system:
    1001% perl -e 'fork || print for split (//, "a" x 10);'
    I get nothing but a string of a's. Suse 9.1, perl 5.8.6.

    -Mark

Re: strange behaviour when forking lots of times
by BrowserUk (Patriarch) on May 16, 2006 at 18:49 UTC

    The behaviour is attributable to running out of resource (specifically C stack) when spawning the threads that underlie Win32's fork emulation. The 1s appear to be residual values from Perl's stack, possibly the return from print, that are being 'assigned' to $_?

    With a standard build of Perl, the 1s creep into the output when the number of concurrent forks (threads) exceeds ~120. Using AS811, using a string length of 9 exceeds this limit and produces a few ones at the end of the run

    perl -le"fork || print qq[$$:$_] for split'', 'abcdefghi';" abcdbcdefghidefg ... [snip] 11h11h1111h1hh1111h1h11h11h11111i11h111111111111111i

    However, if you used a copy of perl that has had it's stack reservation reduced as I described in Use more threads., then you can run many more concurrent threads, and the "strange behaviour" goes away. The following version succeeds in starting well over 13,000 threads before consuming all my swap space and terminating for lack of memory.

    ## WARNING. SERIOUS FORK BOMB tperl -e"fork || print for split'', 'abcdefghijklmnop';"

    Reduce the string to 'a' .. 'n' and it completes successfully with no sign of the mysterious 1s.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: strange behaviour when forking lots of times
by Dervish (Friar) on May 16, 2006 at 08:05 UTC
    It took me a while to understand this code. As you may guess, I, too, am new at Perl but have had many years' work with C. From my C-programming perspective, I interpreted your code as forking and then (if you are the child) executing the command 'print for split (//, "a" x 10)' However, this is one of those areas where Perl is quite different from C. The 'for' is a statement modifier, and so affects the entire command. So 10 child processes are created, each of which forks 9 times, and so on. (Resulting in the 10! processes mentioned above). Just an alternate perspective from someone who's still new at this strange stuff. Dervish
Strange behaviour when copying other people's posts
by liverpole (Monsignor) on Oct 16, 2006 at 21:55 UTC
    When you say:

        Here is my code

    what you forgot to say was that you've simply copied this code from this site, where there's an article written by David Chan, on April 20, 2001 (over 5 years ago!), which says:

    $ perl -we 'fork || print for split //, "a" x 10' when I run that on my computer, I get strange output. Instead of printing "a" 2**10 times, the output contains random "1"'s, like this: aa1aaaaa1aaa1aaaaa1aaa1aaaa1aaa1aaaaaa1aaaaa1aa1aaaaaa1a etc.. I suspect this is due to a failing malloc() or something, but It is silent failure. Apparently similar commands don't output "a"s, e.g.: $ perl -we 'for || print "a" for 1..10' It also affects different computers differently; the "x 10" needs to be replaced by a higher value to get the same effect sometimes (but no +t too high, or you'll fork-bomb your computer).

    For more on the code-copying habits of this poster, see this node.


    s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
Re: strange behaviour when forking lots of times
by jdporter (Chancellor) on Oct 17, 2006 at 00:29 UTC
    "Keep pouring your ideas"

    I guess you mean "keep pouring someone else's ideas"...

Re: strange behaviour when forking lots of times
by codeacrobat (Chaplain) on May 17, 2006 at 15:16 UTC
    You can write a more beautiful script to see the same funny fork errors.
    fork || print for ("a") x 10
    There is need to split here ;-)

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (3)
As of 2024-03-19 11:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found