DESTROY not being called on stop/restart
am 15.09.2009 21:12:21 von Clinton Gormley
Hi all
I'm finding that DESTROY blocks on objects stored in lexical variables
are not being called on apachectl stop / restart.
These lexicals are destroyed as they should be when they go out of
scope.
I've resorted to storing weak refs to these objects in a hash and
cleaning them up with a child exit handler, but from what I read in the
docs, DESTROY blocks should be supported, no?
I'm using mod_perl 2.0.4 with apache 2.2.9, perl 5.10 and a prefork MPM.
any ideas?
thanks
Clint
Re: DESTROY not being called on stop/restart
am 16.09.2009 11:21:40 von Clinton Gormley
On Tue, 2009-09-15 at 14:29 -0500, David Nicol wrote:
> I'm ignorant of internals specifics, but perl's full cleanup on exit
> needs to be called, and is called at an orderly shutdown. It doesn't
> get called at POSIX::exit, or when the process in which the
> interpreter is embedded exits without calling it.
>
> Presumably apache offers a hook for orderly shutdown and mod_perl
> takes advantage of that hook to run an orderly shutdown on the
> embedded interpreter. There is some danger of hanging on exit though,
> so there could be a good argument against not doing that by default.
>
> Graceful is supposed to do a stop/restart allowing requests to
> complete and so on, so it is easy to imagine that the hook might get
> run under a graceful but not under a stop, as stop is used to exit
> even when hung.
>
I'm finding the same problem with a graceful-stop. It may be the nature
of the code that I'm using, which does the following:
To do a search:
---------------
- check for the search in the cache
- if result == $LOCK then go back to previous step
- if no result
- store $LOCK in cache
- lock cache (using lexical object with DESTROY)
- retrieve data from the DB
- if data
- store in cache
- lock expires because of scope
-> DESTROY
-> if data loaded and stored to cache, then do nothing
-> else release lock
- return data
I'm testing it by:
------------------
- locking DB search table with SQL
- clearing the existing cache
- start apache
- make two requests for the same thing
- first locks cache and tries to do query
- second sees lock and waits
- apachectl stop / restart / graceful-stop
- apachectl start
- retry one request
This results in the last request hanging because the lock from the first
request still hasn't been cleared.
It may be because the code doesn't run to completion because the SQL
query never receives a response, but I'd still have expected DESTROY to
be called.
The docs for mod_perl 1 imply that DESTROY blocks are called unless
PERL_DESTRUCT_LEVEL is set to -1:
http://perl.apache.org/docs/1.0/guide/troubleshooting.html#_ warn__child_process_30388_did_not_exit__sending_another_SIGH UP
This environment variable no longer seems to exist, and maybe behaviour
has changed.
Either way, it is a gotcha that should be documented (by somebody who
understands what actually happens when) (... he says, neatly excluding
himself :)
For the record, the child exit handler is being called on
stop/restart/graceful-stop and so handles this situation neatly.
thanks
Clint