Graham Dumpleton
grahamd at dscpl.com.au
Wed Jan 11 17:13:42 EST 2006
jelle wrote .. > I'm trying to use mp_server register_cleanup to dump some collected > runtime stats but need a more explicit code example. > > As I understand it, server.register_cleanup function is called when the > apache child process is terminated. Currently I have an apache directive > set as MaxRequestsPerChild 10 to test that functionality. > > Questions: > > I'm using mp_servlets, should the register_cleanup call be in the mainline > of a commonly imported file or should it be placed in a commonly called > function or either way? > > What is the appropriate import statement? > > Does the callable function expect and parameters? > > What is the complete call look like? In mod_python 2.7 and 3.1, to register a cleanup handler to be executed when the server is shutdown, a call needs to be made to: req.server.register_cleanup() Because the function is accessed via the request object, the call can only be made from with the context of an executing handler where there request object is actually available. Thus: def cleanup(data): ... def handler(req): req.server.register_cleanup(req,cleanup) ... The problem here is that you don't actually want the function to be called everytime the request handler is called. Thus you need to have a flag to indicate whether you have already called it. Presuming you are using a non threaded Apache MPM, you would thus write: flag = False def handler(req): if not flag: flag = True req.server.register_cleanup(req,cleanup) If you are using a multithreaded MPM, access to that flag and the call to register the cleanup function is going to have to be thread protected so that the initialisation isn't done by two different threads at the same time. The next problem you need to contend with is that if module reloading if allowed on this module it will result in registration happening every time the module is reloaded. Thus, you actually need to put the code in a separate module which is not the subject of module reloading. Ie., it should be a distinct module on your PYTHONPATH imported using 'import' and not in the document tree. # myinitmodule.py try: import threading except: import dummy_threading as threading lock = threading.Lock() flag = False def cleanup(data): ... def register_cleanup(req): lock.acquire() if not flag: flag = True req.server.register_cleanup(req,cleanup) lock.release() # handler.py import myinitmodule def handler(req): myinitmodule.register_cleanup(req) ... Having said that, it is not gauranteed that the cleanup handler will actually be called. It will only be called when there is a clean shutdown. If the Apache child process gets hung on shutdown and the parent process has to explicitly kill it, the cleanup handler may not be called. This is compounded by the currently known issue of: http://issues.apache.org/jira/browse/MODPYTHON-109 The above is the portable way of doing it for different versions of mod_python. In mod_python 3.2, you are also able to access the function for registering a cleanup function direct from the 'apache' module. This call does not require the request object to be available. Thus in mod_python 3.2, you can actually say: # myinitmodule.py from mod_python import apache try: import threading except: import dummy_threading as threading lock = threading.Lock() flag = False def cleanup(data): ... def register_cleanup(): lock.acquire() if not flag: flag = True apache.register_cleanup(cleanup) lock.release() # handler.py import myinitmodule myinitmodule.register_cleanup() def handler(req): ... Because in mod_python 3.2 you can do this, you could even use the PythonImport directive to import a module which does the registration and thus avoid having to do it in some handler module. Graham
|