Skip to content

gh-87079: Warn on unintended signal wakeup fd override in asyncio #96807

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

Merged
merged 6 commits into from
Sep 17, 2022

Conversation

hidmic
Copy link
Contributor

@hidmic hidmic commented Sep 13, 2022

Addresses #87079, with a relatively minor change of heart: this patch warns instead of raising an exception. I figured quite a few users may be inadvertently (or even consciously) relying on signal wakeup file descriptor overrides, and an exception may be inconvenient. It turns out even asyncio tests do this, to some extent.

Warnings fulfill the intent of notifying the user and can be trivially promoted to an exception.

@bedevere-bot
Copy link

Most changes to Python require a NEWS entry.

Please add it using the blurb_it web app or the blurb command-line tool.

@ghost
Copy link

ghost commented Sep 13, 2022

All commit authors signed the Contributor License Agreement.
CLA signed

@@ -77,6 +76,7 @@ def close(self):
ResourceWarning,
source=self)
self._signal_handlers.clear()
super().close()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Otherwise, an active signal wakeup file descriptor may be scrapped too early.

Copy link
Member

Choose a reason for hiding this comment

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

At the very least this deserves to be a comment in the source code. IIUC super().close() is selector_events.BaseSelectorEventLoop.close(), which closes the socketpair, and that would break the check you've added to remove_signal_handler(). But I'm not sure I like that check, see below.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Comment added in 3b4975a.

@gvanrossum
Copy link
Member

@hidmic Can you sign the CLA and add a news blurb? CLick on Details for the failing tests for instructions.

@hidmic hidmic force-pushed the cope-with-issue-87079 branch from 3f64700 to bec6ccd Compare September 14, 2022 22:10
@bedevere-bot
Copy link

Most changes to Python require a NEWS entry.

Please add it using the blurb_it web app or the blurb command-line tool.

@hidmic
Copy link
Contributor Author

hidmic commented Sep 14, 2022

Can you sign the CLA and add a news blurb?

@gvanrossum done and done.

Comment on lines 641 to 642
'Overriding signal wakeup file '
'descriptor for loop signal handlers',
Copy link
Member

Choose a reason for hiding this comment

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

I no longer like string literals split across lines like this, it makes phrase searching harder. Also I'm trying to clarify the warning.

Suggested change
'Overriding signal wakeup file '
'descriptor for loop signal handlers',
"Signal wakeup fd was already set",

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in bc7b849.

Comment on lines 108 to 109
'Overriding signal wakeup file '
'descriptor for loop signal handlers',
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
'Overriding signal wakeup file '
'descriptor for loop signal handlers',
"Signal wakeup fd was already set",

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in bc7b849.

@@ -77,6 +76,7 @@ def close(self):
ResourceWarning,
source=self)
self._signal_handlers.clear()
super().close()
Copy link
Member

Choose a reason for hiding this comment

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

At the very least this deserves to be a comment in the source code. IIUC super().close() is selector_events.BaseSelectorEventLoop.close(), which closes the socketpair, and that would break the check you've added to remove_signal_handler(). But I'm not sure I like that check, see below.

Comment on lines 169 to 181
signal.set_wakeup_fd(-1)
oldfd = signal.set_wakeup_fd(-1)
if oldfd != -1 and oldfd != self._csock.fileno():
warnings.warn(
'Got unexpected signal wakeup file '
'descriptor while removing it',
ResourceWarning,
source=self)
Copy link
Member

Choose a reason for hiding this comment

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

I don't really like warnings being issued when closing things -- they aren't very actionable. I understand this is trying to alert the user that something else might have set the wakeup fd, overriding ours. But if we made it this far there's not much we can do about it, is there?

(OTOH maybe this could be logged in debug mode?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But if we made it this far there's not much we can do about it, is there?

That's fair, though I don't expect the user to act on the warning programmatically, even if they could. It's a hint.

OTOH maybe this could be logged in debug mode?

I think that reduces the value of the hint. I would like to know that my application is potentially broken ASAP, rather than waiting for it to manifest itself somehow to even consider looking at debug logs.

Copy link
Member

Choose a reason for hiding this comment

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

Fair enough. I'll hold off for a little bit and then merge.

@@ -684,7 +690,13 @@ def close(self):
return

if threading.current_thread() is threading.main_thread():
signal.set_wakeup_fd(-1)
oldfd = signal.set_wakeup_fd(-1)
if oldfd == self._csock.fileno():
Copy link
Member

Choose a reason for hiding this comment

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

Is this maybe backwards? In the unix code you use !=.

Separately, the same concern about warnings during closing as for the unix version.

And maybe the error message doesn't have to be split (it's not the end of the world if it's a little too long :-).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is this maybe backwards? In the unix code you use !=.

Indeed 🤦‍♂️ Fixed in bc7b849.

self.loop.close()
with mock.patch('signal.set_wakeup_fd') as set_wakeup_fd:
set_wakeup_fd.return_value = -1000
self.loop.close()
Copy link
Member

Choose a reason for hiding this comment

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

I guess this test needs to row an assertWarnsRegex call? (See my comment on the code in the file under test.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeap, that's right too... This is an incredibly sloppy patch. It shows I did it on a rush. Sorry for that. Fixed in bc7b849.

Comment on lines +1 to +2
Warn the user whenever asyncio event loops override a signal wake up file
descriptor that was previously set.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Warn the user whenever asyncio event loops override a signal wake up file
descriptor that was previously set.
:mod:`asyncio` now emits :exc:`ResourceWarning` when overriding signal wakeup fd if it was previously set.

Copy link
Member

Choose a reason for hiding this comment

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

Well dang I missed this comment and merged without applying that. Sorry about that (I fail at scrolling). I think this isn't so important that we need to send another PR, but if you insist I'll gladly merge it.

Copy link
Contributor

Choose a reason for hiding this comment

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

No worries, it was just a minor suggestion.

Copy link
Contributor

@kumaraditya303 kumaraditya303 left a comment

Choose a reason for hiding this comment

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

LGTM with minor news suggestion.

@gvanrossum gvanrossum merged commit 0587810 into python:main Sep 17, 2022
@gvanrossum
Copy link
Member

Thanks @hidmic for the patch!

@kumaraditya303
Copy link
Contributor

Seems like this broke some openssl bots. See https://github.com/python/cpython/actions/runs/3073806792/jobs/4966172052 on main

@gvanrossum
Copy link
Member

Seems like this broke some openssl bots. See https://github.com/python/cpython/actions/runs/3073806792/jobs/4966172052 on main

Oh, that's unfortunate. Unless either of you has a quick fix, we should probably revert.

@gvanrossum
Copy link
Member

I can repro the failure by running ./python.exe Lib/test/ssltests.py on my Mac. I'm just going to revert this, so you can come up with a fix without stressing out about it.

gvanrossum added a commit that referenced this pull request Sep 17, 2022
gvanrossum added a commit that referenced this pull request Sep 17, 2022
…yncio` (#96807)" (#96898)

This reverts commit 0587810.
Reason: This broke buildbots (some warnings added by that commit are turned to errors in the SSL buildbot).
Repro:  ./python Lib/test/ssltests.py
@hidmic hidmic deleted the cope-with-issue-87079 branch September 17, 2022 22:09
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.

4 participants