Skip to content

Commit 087570a

Browse files
tirkarthivsajip
authored andcommitted
bpo-33978: Close existing handlers before logging (re-)configuration. (GH-8008)
1 parent c6cd164 commit 087570a

File tree

3 files changed

+88
-4
lines changed

3 files changed

+88
-4
lines changed

Lib/logging/config.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ def fileConfig(fname, defaults=None, disable_existing_loggers=True):
7373
# critical section
7474
logging._acquireLock()
7575
try:
76-
logging._handlers.clear()
77-
del logging._handlerList[:]
76+
_clearExistingHandlers()
77+
7878
# Handlers add themselves to logging._handlers
7979
handlers = _install_handlers(cp, formatters)
8080
_install_loggers(cp, handlers, disable_existing_loggers)
@@ -265,6 +265,14 @@ def _install_loggers(cp, handlers, disable_existing):
265265
# logger.disabled = 1
266266
_handle_existing_loggers(existing, child_loggers, disable_existing)
267267

268+
269+
def _clearExistingHandlers():
270+
"""Clear and close existing handlers"""
271+
logging._handlers.clear()
272+
logging.shutdown(logging._handlerList[:])
273+
del logging._handlerList[:]
274+
275+
268276
IDENTIFIER = re.compile('^[a-z_][a-z0-9_]*$', re.I)
269277

270278

@@ -524,8 +532,7 @@ def configure(self):
524532
else:
525533
disable_existing = config.pop('disable_existing_loggers', True)
526534

527-
logging._handlers.clear()
528-
del logging._handlerList[:]
535+
_clearExistingHandlers()
529536

530537
# Do formatters first - they don't refer to anything else
531538
formatters = config.get('formatters', EMPTY_DICT)

Lib/test/test_logging.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,6 +1089,7 @@ class ConfigFileTest(BaseTest):
10891089

10901090
"""Reading logging config from a .ini-style config file."""
10911091

1092+
check_no_resource_warning = support.check_no_resource_warning
10921093
expected_log_pat = r"^(\w+) \+\+ (\w+)$"
10931094

10941095
# config0 is a standard configuration.
@@ -1297,6 +1298,27 @@ class ConfigFileTest(BaseTest):
12971298
datefmt=
12981299
"""
12991300

1301+
# config 8, check for resource warning
1302+
config8 = r"""
1303+
[loggers]
1304+
keys=root
1305+
1306+
[handlers]
1307+
keys=file
1308+
1309+
[formatters]
1310+
keys=
1311+
1312+
[logger_root]
1313+
level=DEBUG
1314+
handlers=file
1315+
1316+
[handler_file]
1317+
class=FileHandler
1318+
level=DEBUG
1319+
args=("{tempfile}",)
1320+
"""
1321+
13001322
disable_test = """
13011323
[loggers]
13021324
keys=root
@@ -1442,6 +1464,29 @@ def test_config7_ok(self):
14421464
# Original logger output is empty.
14431465
self.assert_log_lines([])
14441466

1467+
def test_config8_ok(self):
1468+
1469+
def cleanup(h1, fn):
1470+
h1.close()
1471+
os.remove(fn)
1472+
1473+
with self.check_no_resource_warning():
1474+
fd, fn = tempfile.mkstemp(".log", "test_logging-X-")
1475+
os.close(fd)
1476+
1477+
# Replace single backslash with double backslash in windows
1478+
# to avoid unicode error during string formatting
1479+
if os.name == "nt":
1480+
fn = fn.replace("\\", "\\\\")
1481+
1482+
config8 = self.config8.format(tempfile=fn)
1483+
1484+
self.apply_config(config8)
1485+
self.apply_config(config8)
1486+
1487+
handler = logging.root.handlers[0]
1488+
self.addCleanup(cleanup, handler, fn)
1489+
14451490
def test_logger_disabling(self):
14461491
self.apply_config(self.disable_test)
14471492
logger = logging.getLogger('some_pristine_logger')
@@ -2022,6 +2067,7 @@ class ConfigDictTest(BaseTest):
20222067

20232068
"""Reading logging config from a dictionary."""
20242069

2070+
check_no_resource_warning = support.check_no_resource_warning
20252071
expected_log_pat = r"^(\w+) \+\+ (\w+)$"
20262072

20272073
# config0 is a standard configuration.
@@ -2896,6 +2942,35 @@ def test_config14_ok(self):
28962942
logging.warning('Exclamation')
28972943
self.assertTrue(output.getvalue().endswith('Exclamation!\n'))
28982944

2945+
def test_config15_ok(self):
2946+
2947+
def cleanup(h1, fn):
2948+
h1.close()
2949+
os.remove(fn)
2950+
2951+
with self.check_no_resource_warning():
2952+
fd, fn = tempfile.mkstemp(".log", "test_logging-X-")
2953+
os.close(fd)
2954+
2955+
config = {
2956+
"version": 1,
2957+
"handlers": {
2958+
"file": {
2959+
"class": "logging.FileHandler",
2960+
"filename": fn
2961+
}
2962+
},
2963+
"root": {
2964+
"handlers": ["file"]
2965+
}
2966+
}
2967+
2968+
self.apply_config(config)
2969+
self.apply_config(config)
2970+
2971+
handler = logging.root.handlers[0]
2972+
self.addCleanup(cleanup, handler, fn)
2973+
28992974
def setup_via_listener(self, text, verify=None):
29002975
text = text.encode("utf-8")
29012976
# Ask for a randomly assigned port (by using port 0)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Closed existing logging handlers before reconfiguration via fileConfig
2+
and dictConfig. Patch by Karthikeyan Singaravelan.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy