Merge "Fix fd leak from get_logger() in python 2.6"
This commit is contained in:
commit
076634e23c
|
@ -28,6 +28,7 @@ import threading as stdlib_threading
|
|||
import time
|
||||
import uuid
|
||||
import functools
|
||||
import weakref
|
||||
from hashlib import md5, sha1
|
||||
from random import random, shuffle
|
||||
from urllib import quote as _quote
|
||||
|
@ -848,6 +849,22 @@ def timing_stats(**dec_kwargs):
|
|||
return decorating_func
|
||||
|
||||
|
||||
class LoggingHandlerWeakRef(weakref.ref):
|
||||
"""
|
||||
Like a weak reference, but passes through a couple methods that logging
|
||||
handlers need.
|
||||
"""
|
||||
def close(self):
|
||||
referent = self()
|
||||
if referent:
|
||||
referent.close()
|
||||
|
||||
def flush(self):
|
||||
referent = self()
|
||||
if referent:
|
||||
referent.flush()
|
||||
|
||||
|
||||
# double inheritance to support property with setter
|
||||
class LogAdapter(logging.LoggerAdapter, object):
|
||||
"""
|
||||
|
@ -1131,6 +1148,32 @@ def get_logger(conf, name=None, log_to_console=False, log_route=None,
|
|||
print >>sys.stderr, 'Error calling custom handler [%s]' % hook
|
||||
except ValueError:
|
||||
print >>sys.stderr, 'Invalid custom handler format [%s]' % hook
|
||||
|
||||
# Python 2.6 has the undesirable property of keeping references to all log
|
||||
# handlers around forever in logging._handlers and logging._handlerList.
|
||||
# Combine that with handlers that keep file descriptors, and you get an fd
|
||||
# leak.
|
||||
#
|
||||
# And no, we can't share handlers; a SyslogHandler has a socket, and if
|
||||
# two greenthreads end up logging at the same time, you could get message
|
||||
# overlap that garbles the logs and makes eventlet complain.
|
||||
#
|
||||
# Python 2.7 uses weakrefs to avoid the leak, so let's do that too.
|
||||
if sys.version_info[0] == 2 and sys.version_info[1] <= 6:
|
||||
try:
|
||||
logging._acquireLock() # some thread-safety thing
|
||||
for handler in adapted_logger.logger.handlers:
|
||||
if handler in logging._handlers:
|
||||
wr = LoggingHandlerWeakRef(handler)
|
||||
del logging._handlers[handler]
|
||||
logging._handlers[wr] = 1
|
||||
for i, handler_ref in enumerate(logging._handlerList):
|
||||
if handler_ref is handler:
|
||||
logging._handlerList[i] = LoggingHandlerWeakRef(
|
||||
handler)
|
||||
finally:
|
||||
logging._releaseLock()
|
||||
|
||||
return adapted_logger
|
||||
|
||||
|
||||
|
|
|
@ -120,6 +120,10 @@ class MockSys():
|
|||
self.stdio_fds = [self.stdin.fileno(), self.stdout.fileno(),
|
||||
self.stderr.fileno()]
|
||||
|
||||
@property
|
||||
def version_info(self):
|
||||
return sys.version_info
|
||||
|
||||
|
||||
def reset_loggers():
|
||||
if hasattr(utils.get_logger, 'handler4logger'):
|
||||
|
|
Loading…
Reference in New Issue