Skip to content
15 changes: 13 additions & 2 deletions Lib/logging/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,9 +285,20 @@ def _install_loggers(cp, handlers, disable_existing):


def _clearExistingHandlers():
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we call this _clearExistingHandlers() after we applied all the modifications from config, not before as it's happening now?

Copy link
Contributor Author

@Agent-Hellboy Agent-Hellboy Dec 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added a check

#Remove any existing handlers

here as well to counter it , I will do that for fileconfig as well

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we rename the method to better reflect its behaviour? To something like _clearNotUsedHandlers.

"""Clear and close existing handlers"""
"""Clear and close handlers that are no longer in use."""
active_handlers = {
handler
for logger in logging.Logger.manager.loggerDict.values()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason why now the test is passing is that the root logger is not included in manager.loggerDict(). If you change the following line in the test

root_logger = logging.getLogger()

to

root_logger = logging.getLogger("any-logger")

the test will fail.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry, I simply copied your test without giving a thought

if isinstance(logger, logging.Logger)
for handler in logger.handlers
}

for handler_ref in list(logging._handlers.values()):
handler = handler_ref() if callable(handler_ref) else handler_ref
if handler and handler not in active_handlers:
handler.close()

logging._handlers.clear()
logging.shutdown(logging._handlerList[:])
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the logging.shutdown() method calls handler.acquire(), handler.flush() and handler.release(). Also, it iterate all these handlers in a specific order (not sure why).

Don't we need all these actions here?

Copy link
Contributor Author

@Agent-Hellboy Agent-Hellboy Dec 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, it iterate all these handlers in a specific order (not sure why)

didn't get your question, it is to protect the handler in a concurrent environment. A mutex lock , acquire operation release

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My question is why your implementation in this PR doesn't used them?

del logging._handlerList[:]


Expand Down
21 changes: 21 additions & 0 deletions Lib/test/test_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -3554,6 +3554,27 @@ def test_config15_ok(self):
handler = logging.root.handlers[0]
self.addCleanup(closeFileHandler, handler, fn)

def test_disable_existing_loggers(self):
fn = make_temp_file(".log", "test_logging-disable-existing-loggers-")
file_handler = logging.FileHandler(fn, mode="w")
file_handler.setFormatter(logging.Formatter("%(message)s"))
root_logger = logging.getLogger()
root_logger.addHandler(file_handler)

config = {"version": 1, "disable_existing_loggers": False}

# we have disable_existing_loggers=False,
# so, all handlers should continue working
self.apply_config(config)

msg = "test message"
logging.warning(msg)
file_handler.close()
with open(fn, encoding='utf-8') as f:
data = f.read().strip()
os.remove(fn)
self.assertEqual(data, msg)

def test_config16_ok(self):
self.apply_config(self.config16)
h = logging._handlers['hand1']
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Avoid shutting down handlers during reconfiguration
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should clarify that this is related to the logging module.

Loading