-
-
Notifications
You must be signed in to change notification settings - Fork 402
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
bot: fix race-condition in dispatch #1728
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not many notes, relative to the patch size. But you weren't kidding about it being doc-heavy!
082ba78
to
608f673
Compare
Fixed!
Yup, and I believe an overhaul of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apply this one last single-letter change and squash away. 🚀
6b8d4ba
to
2ec778f
Compare
All squashed into one single commit! |
@Exirel This is approaching the top of the merge queue, but it has a conflict now. :/ |
The scenario is: * dispatch is called for a pretrigger * it looks into the list of callable by priority * it triggers one of the first callables, which wants to remove a callable of the same priority * because Python must not allow a dict to be modified while it is iterated over, Python raises an exception If we put a lock here, Python won't raise the exception... but we'll get a deadlock. To prevent that, instead, we copy the list of callables, and return the ones that are triggered. If any of them wants to change the callables of the same priority, they won't raise an error, because we are not iterating anymore on the dict. Hoo-ray! (with applied review suggestions from dgw) Co-Authored-By: dgw <dgw@technobabbl.es>
2ec778f
to
59704e6
Compare
Conflict fixed. That was just the little |
Assigning the tuple returned by `_is_pretrigger_blocked()` to both vars instead of unpacking the values makes both of them always evaluate to `True` in Boolean contexts. Which magically blocks everyone from doing anything, unless `get_triggered_callables()` decides they're unblockable by virtue of `trigger.admin` being `True` (or if the function is marked unblockable, of course). Fun times! Introduced by #1728 — `.blame Exirel`! I share no responsibility for missing this in code review. Nope, none at all. :P Let this be a lesson to us all: Test things as a non-admin sometimes. Just in case. (New testing infrastructure should help us catch this sort of thing automatically in a lot of cases, once our unit tests have been updated to use the new mocks.)
The scenario is:
If we put a lock here, Python won't raise the exception... but we'll get a deadlock. To prevent that, instead, we copy the list of callables, and return the ones that are triggered. If any of them wants to change the callables of the same priority, they won't raise an error, because we are not iterating anymore on the dict.
Hoo-ray!
@dgw have fun with my miserable grammar at 2am.