Nic Ferrier wrote:
Jim Gallacher <[EMAIL PROTECTED]> writes:
There is a typo in your code: s/logging.debug/logging.DEBUG/
Got me. It ran for me though...
Beyond that it still segfaults for me.
I can't get it to segfault.
Can you share your test?
Sure, but it's not doing anything fancy.
Debian Sid, apache2-mpm-prefork 2.0.54, python 2.3.5, mod_python 3.2.2b.
The ApacheLogHandler class is in module mod_python/future/mplog.py
Using mod_python.publisher handler:
test.py
-------
from mod_python.future.mplog import ApacheLogHandler
import logging
def index(req):
return '''<html><body>
<a href="test.py/segfault">seg fault</a><br />
<a href="test.py/no_segfault">no seg fault</a><br />
</body></html>'''
def segfault(req):
log = logging.getLogger()
hdlr = ApacheLogHandler(req)
log.addHandler(hdlr)
log.critical('test.segfault: seg fault?')
return '''removeHandler cleanup NOT registered:
check the log for a segfault'''
def no_segfault(req):
log = logging.getLogger()
hdlr = ApacheLogHandler(req)
log.addHandler(hdlr)
req.register_cleanup(log.removeHandler, hdlr)
log.critical('test.no_segfault: seg fault?')
return '''removeHandler cleanup registered:
check the log for a segfault'''
The other problem is that you are not removing the handler instance
from the logging instance so you still have a memory leak. 100k
requests would result in 100k handler instances. Oh, and there might
be a bit of a performance issue when emit() gets fired 100k
times. ;)
Good point... here's another one:
# A log handler for mod-python
import logging
from mod_python import apache
class ApacheLogHandler(logging.Handler):
"""A handler class which sends all logging to Apache."""
def __init__(self, request):
"""
Initialize the handler (does nothing)
"""
logging.Handler.__init__(self)
self.request = request
def cleanup(data = None):
self.request = None
logging.getLogger().removeHandler(self)
request.register_cleanup(cleanup)
# Set up the thing
self.level_mapping = { }
self.level_mapping[logging.CRITICAL] = apache.APLOG_CRIT
self.level_mapping[logging.ERROR] = apache.APLOG_ERR
self.level_mapping[logging.WARNING] = apache.APLOG_WARNING
self.level_mapping[logging.INFO] = apache.APLOG_INFO
self.level_mapping[logging.DEBUG] = apache.APLOG_DEBUG
def emit(self, record):
"""Emit a record."""
msg = self.format(record)
if self.request != None:
self.request.log_error(msg, self.level_mapping[record.levelno])
# We *could* log to apache here:
#else:
# apache.log(msg)
# End
This version does not segfault, and should take care of the memory leak
but only for the root logger. If the user specifies a different logger...
log = logging.getLogger('myLooger')
... we are back to the potential segfault problems.
I also want to mention that there will be a performance impact in using
logging since only one thread can access the logging object at a time.
I'm including this comment now just in case I forget later. Not a big
deal but it is something that should be considered for a high traffic
site and is an argument for not using the standard python logging
facility internally in mod_python... which Nic was *not* asking for
anyway. :)
Regards,
Jim