[Catalyst] Re: Have exceeded the maximum number of attempts (1000) to open temp file/dir

Bill Moseley moseley at hank.org
Wed Nov 6 19:19:05 GMT 2013

On Mon, Nov 4, 2013 at 4:20 PM, neil.lunn <neil at mylunn.id.au> wrote:

> I'd be thinking along the lines of mod_perl is evil. From a quick google
> of "mod_perl srand" there seem to be some similar cases. And a where to
> call srand in this post:
> http://blogs.perl.org/users/brian_phillips/2010/06/when-rand-isnt-random.=
> Give it a try.

Thanks.  That indeed was part of the problem.   Other part was a leak.

First, our code to manage database replication was causing a leak of $c.
That's why I could not replicate in dev where I don't normally run with a
replicated database.

The result was that a temp file would be created but not destroyed at the
end of the request.  It would be destroyed at the start of the *next*

So, the temp files would be deleted, but just not at the right time.   The
one exception was the last request -- when Apache killed off a child
process then that final temp file would be left behind.

Here's where mod_perl comes in.

If I understand Perl correctly, the first time rand() is called a new seed
is generated.   So, if you fork a bunch of children and each calls rand()
each will get a new seed.   But, if you explicitly call srand()  once in
the parent before forking then all the children get the same seed, and all
the children will generate the same random sequence.

When using Starman or even the forking test server this is not a problem as
I believe they both call srand() for each child.   With Apache the children
end up with the same seed which likely means the parent process called
rand() or srand().

Over time, /tmp would fill, and fill with a pre-defined set of filenames
due to the common seed eventually the first 1000 names would get used up.

My fix is simply this in the app base class:

my $srand;
before handle_request =3D> sub { srand() unless $srand++ };

The question if this is something Catalyst should handle.

As for the leak, we use the same replication code in different apps -- so
need a way for the specific app to work with this.

The broken code was in an ACCEPT_CONTEXT that included:

$replication_object->callback( sub { $self->callback_method( $c ) } );

I'm not thrilled by $c getting passed here, but the callback need quite a
bit from $c.

The "fix" that seems to work is simply this:

weaken( $c );
$replication_object->callback( sub { $self->callback_method( $c ) } );

-- =

Bill Moseley
moseley at hank.org
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.scsys.co.uk/pipermail/catalyst/attachments/20131106/ad8a9=

More information about the Catalyst mailing list