Skip to content

gh-116267: Avoid formatting record twice in RotatingFileHandler. #122731

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

vsajip
Copy link
Member

@vsajip vsajip commented Aug 6, 2024

@vsajip vsajip added skip news 🔨 test-with-buildbots Test PR w/ buildbots; report in status section labels Aug 6, 2024
@bedevere-bot
Copy link

🤖 New build scheduled with the buildbot fleet by @vsajip for commit 8323c0f 🤖

If you want to schedule another build, you need to add the 🔨 test-with-buildbots label again.

@bedevere-bot bedevere-bot removed the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Aug 6, 2024
@vsajip vsajip added the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Aug 6, 2024
@bedevere-bot
Copy link

🤖 New build scheduled with the buildbot fleet by @vsajip for commit 9984c5f 🤖

If you want to schedule another build, you need to add the 🔨 test-with-buildbots label again.

@bedevere-bot bedevere-bot removed the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Aug 6, 2024
@vsajip
Copy link
Member Author

vsajip commented Aug 7, 2024

Only two buildbot test failures, neither of which seems relevant to the change.

@vsajip vsajip requested a review from serhiy-storchaka August 7, 2024 10:36
Copy link
Member

@serhiy-storchaka serhiy-storchaka left a comment

Choose a reason for hiding this comment

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

Frankly, this is awful. This is almost like using global variable to return a value from function. But I do not see a better way for now.

self._msg = None
else:
msg = self.format(record)
self.stream.write(msg + self.terminator)
Copy link
Member

Choose a reason for hiding this comment

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

FileHandler.emit() opens a stream if it was not open. If you want to use the cached formatted message, this should perhaps be done in FileHandler.emit() or StreamHandler.emit(). Or inline FileHandler.emit() and StreamHandler.emit() completely here. Or add parameter for formatted error message in FileHandler.emit() and StreamHandler.emit().

Copy link
Member Author

Choose a reason for hiding this comment

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

FileHandler.emit() opens a stream if it was not open

True, but it's opened in shouldRollover(), so that part of FileHandler.emit() would never be exercised.

if self.stream is None: # delay was set...
self.stream = self._open()

Copy link
Member

Choose a reason for hiding this comment

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

You are right. Although it may break subclasses that override shouldRollover() (if it returns early, before calling super().shouldRollover()).

@@ -195,10 +202,11 @@ def shouldRollover(self, record):
"""
if self.stream is None: # delay was set...
self.stream = self._open()
pos = self.stream.tell()
Copy link
Member

Choose a reason for hiding this comment

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

Seems it is not used.

Copy link
Member Author

Choose a reason for hiding this comment

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

You're right, it's related to a fix #116263 and can be removed here.

else:
msg = self.format(record)
self.stream.write(msg + self.terminator)
self.flush()
except Exception:
Copy link
Member

Choose a reason for hiding this comment

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

This is not related to this issue, but there should be the RecursionError handler (see bpo-36272). And in many other places that call handleError().

@vsajip
Copy link
Member Author

vsajip commented Aug 7, 2024

Frankly, this is awful

I agree it's not pretty, but I'm not sure I'd go that far. Practicality beats purity?

Copy link
Member

@serhiy-storchaka serhiy-storchaka left a comment

Choose a reason for hiding this comment

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

In general LGTM. This is ugly, but I have no better ideas.

I have only two suggestions:

msg = self.format(record)
self.stream.write(msg + self.terminator)
self.flush()
except RecursionError: # See issue bpo-36272
Copy link
Member

Choose a reason for hiding this comment

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

I think that it is better to open a separate issue for this. There may be other problems related to handling RecursionError here. For example, in SocketHandler we may want to close socket on RecursionError if closeOnError is true.

self._msg = None
else:
msg = self.format(record)
self.stream.write(msg + self.terminator)
Copy link
Member

Choose a reason for hiding this comment

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

You are right. Although it may break subclasses that override shouldRollover() (if it returns early, before calling super().shouldRollover()).

@vsajip
Copy link
Member Author

vsajip commented Aug 7, 2024

I would prefer to merge #122788

OK, we can park this PR for now.

I think that it is better to open a separate issue for this. There may be other problems related to handling RecursionError here. For example, in SocketHandler we may want to close socket on RecursionError if closeOnError is true.

Fair enough.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants