Commit 087570af authored by Xtreak's avatar Xtreak Committed by Vinay Sajip

bpo-33978: Close existing handlers before logging (re-)configuration. (GH-8008)

parent c6cd164c
...@@ -73,8 +73,8 @@ def fileConfig(fname, defaults=None, disable_existing_loggers=True): ...@@ -73,8 +73,8 @@ def fileConfig(fname, defaults=None, disable_existing_loggers=True):
# critical section # critical section
logging._acquireLock() logging._acquireLock()
try: try:
logging._handlers.clear() _clearExistingHandlers()
del logging._handlerList[:]
# Handlers add themselves to logging._handlers # Handlers add themselves to logging._handlers
handlers = _install_handlers(cp, formatters) handlers = _install_handlers(cp, formatters)
_install_loggers(cp, handlers, disable_existing_loggers) _install_loggers(cp, handlers, disable_existing_loggers)
...@@ -265,6 +265,14 @@ def _install_loggers(cp, handlers, disable_existing): ...@@ -265,6 +265,14 @@ def _install_loggers(cp, handlers, disable_existing):
# logger.disabled = 1 # logger.disabled = 1
_handle_existing_loggers(existing, child_loggers, disable_existing) _handle_existing_loggers(existing, child_loggers, disable_existing)
def _clearExistingHandlers():
"""Clear and close existing handlers"""
logging._handlers.clear()
logging.shutdown(logging._handlerList[:])
del logging._handlerList[:]
IDENTIFIER = re.compile('^[a-z_][a-z0-9_]*$', re.I) IDENTIFIER = re.compile('^[a-z_][a-z0-9_]*$', re.I)
...@@ -524,8 +532,7 @@ class DictConfigurator(BaseConfigurator): ...@@ -524,8 +532,7 @@ class DictConfigurator(BaseConfigurator):
else: else:
disable_existing = config.pop('disable_existing_loggers', True) disable_existing = config.pop('disable_existing_loggers', True)
logging._handlers.clear() _clearExistingHandlers()
del logging._handlerList[:]
# Do formatters first - they don't refer to anything else # Do formatters first - they don't refer to anything else
formatters = config.get('formatters', EMPTY_DICT) formatters = config.get('formatters', EMPTY_DICT)
......
...@@ -1089,6 +1089,7 @@ class ConfigFileTest(BaseTest): ...@@ -1089,6 +1089,7 @@ class ConfigFileTest(BaseTest):
"""Reading logging config from a .ini-style config file.""" """Reading logging config from a .ini-style config file."""
check_no_resource_warning = support.check_no_resource_warning
expected_log_pat = r"^(\w+) \+\+ (\w+)$" expected_log_pat = r"^(\w+) \+\+ (\w+)$"
# config0 is a standard configuration. # config0 is a standard configuration.
...@@ -1297,6 +1298,27 @@ class ConfigFileTest(BaseTest): ...@@ -1297,6 +1298,27 @@ class ConfigFileTest(BaseTest):
datefmt= datefmt=
""" """
# config 8, check for resource warning
config8 = r"""
[loggers]
keys=root
[handlers]
keys=file
[formatters]
keys=
[logger_root]
level=DEBUG
handlers=file
[handler_file]
class=FileHandler
level=DEBUG
args=("{tempfile}",)
"""
disable_test = """ disable_test = """
[loggers] [loggers]
keys=root keys=root
...@@ -1442,6 +1464,29 @@ class ConfigFileTest(BaseTest): ...@@ -1442,6 +1464,29 @@ class ConfigFileTest(BaseTest):
# Original logger output is empty. # Original logger output is empty.
self.assert_log_lines([]) self.assert_log_lines([])
def test_config8_ok(self):
def cleanup(h1, fn):
h1.close()
os.remove(fn)
with self.check_no_resource_warning():
fd, fn = tempfile.mkstemp(".log", "test_logging-X-")
os.close(fd)
# Replace single backslash with double backslash in windows
# to avoid unicode error during string formatting
if os.name == "nt":
fn = fn.replace("\\", "\\\\")
config8 = self.config8.format(tempfile=fn)
self.apply_config(config8)
self.apply_config(config8)
handler = logging.root.handlers[0]
self.addCleanup(cleanup, handler, fn)
def test_logger_disabling(self): def test_logger_disabling(self):
self.apply_config(self.disable_test) self.apply_config(self.disable_test)
logger = logging.getLogger('some_pristine_logger') logger = logging.getLogger('some_pristine_logger')
...@@ -2022,6 +2067,7 @@ class ConfigDictTest(BaseTest): ...@@ -2022,6 +2067,7 @@ class ConfigDictTest(BaseTest):
"""Reading logging config from a dictionary.""" """Reading logging config from a dictionary."""
check_no_resource_warning = support.check_no_resource_warning
expected_log_pat = r"^(\w+) \+\+ (\w+)$" expected_log_pat = r"^(\w+) \+\+ (\w+)$"
# config0 is a standard configuration. # config0 is a standard configuration.
...@@ -2896,6 +2942,35 @@ class ConfigDictTest(BaseTest): ...@@ -2896,6 +2942,35 @@ class ConfigDictTest(BaseTest):
logging.warning('Exclamation') logging.warning('Exclamation')
self.assertTrue(output.getvalue().endswith('Exclamation!\n')) self.assertTrue(output.getvalue().endswith('Exclamation!\n'))
def test_config15_ok(self):
def cleanup(h1, fn):
h1.close()
os.remove(fn)
with self.check_no_resource_warning():
fd, fn = tempfile.mkstemp(".log", "test_logging-X-")
os.close(fd)
config = {
"version": 1,
"handlers": {
"file": {
"class": "logging.FileHandler",
"filename": fn
}
},
"root": {
"handlers": ["file"]
}
}
self.apply_config(config)
self.apply_config(config)
handler = logging.root.handlers[0]
self.addCleanup(cleanup, handler, fn)
def setup_via_listener(self, text, verify=None): def setup_via_listener(self, text, verify=None):
text = text.encode("utf-8") text = text.encode("utf-8")
# Ask for a randomly assigned port (by using port 0) # Ask for a randomly assigned port (by using port 0)
......
Closed existing logging handlers before reconfiguration via fileConfig
and dictConfig. Patch by Karthikeyan Singaravelan.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment