develooper Front page | perl.perl5.porters | Postings from November 2011

Re: [perl #6847] strange behaviour when forking lots of times

Thread Previous | Thread Next
From:
Aaron Crane
Date:
November 23, 2011 02:46
Subject:
Re: [perl #6847] strange behaviour when forking lots of times
Message ID:
CACmk_tu6kChCGwNFAyQcZKDJDr=GN2nnjbe9VOV=tKmTpvdKew@mail.gmail.com
James E Keenan via RT <perlbug-followup@perl.org> wrote:
> On Sat Apr 21 01:36:46 2001, dpc29@cam.ac.uk wrote:
>> $ 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
>>
>> It also affects different computers differently; the "x 10" needs to
>> be replaced by a higher value to get the same effect sometimes (but
>> not too high, or you'll fork-bomb your computer).
>
> I have recently confirmed that this behavior still exists.  It taught me
> the meaning of 'fork-bomb'. :-(

A hypothesis: this is being run with an RLIMIT_NPROC in place (aka
`ulimit -u`).  In particular, if RLIMIT_NPROC is at or near 2**n, then
some of the forks are likely to fail with EAGAIN when the literal 10
in the code is replaced with an integer >= n; whereas choosing a lower
number will make things work.  That certainly matches the behaviour
I'm seeing.  This slightly modified code should emit "a" in every
child process, "1" if the fork failed with EAGAIN, or "0" if the fork
failed for some other reason:

$ ulimit -u
266
$ perl -MErrno=EAGAIN -we '(fork // print 0 + ($! == EAGAIN)) || print
for split //, "a" x 8'; sleep 0.2; echo
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1aa11a11a1aa11aa11aa11aaa1111aaaaa11aaaaaaaaaaaaaaaaaaaaaaaaaaaaa11aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

So when we can have just over 2**8 processes, and we try to start
(2**8)-1 in very quick succession, we get some EAGAIN failures, as
expected.  If we try to start only (2**7)-1 processes, they all
succeed:

$ perl -MErrno=EAGAIN -we '(fork // print 0 + ($! == EAGAIN)) || print
for split //, "a" x 7'; sleep 0.2; echo
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

But if we then reduce the ulimit again, we see more errors:

$ ulimit -u 128
$ perl -MErrno=EAGAIN -we '(fork // print 0 + ($! == EAGAIN)) || print
for split //, "a" x 7'; sleep 0.2; echo
aaaa11a111111a1111111a1111a111111a1111a111a1

If I'm right about this, I don't think there's a bug here.

-- 
Aaron Crane ** http://aaroncrane.co.uk/

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About