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
FIX(plugins): Use atomic operations in Link plugin #6075
Conversation
7dc5928
to
07986e3
Compare
(Be assured that reviewing this is on my TODO list - the PR has not been forgotten. I just don't have the time to do it atm) |
07986e3
to
6a12192
Compare
I'm wondering whether we have a way to ensure that each individual member in |
6a12192
to
ebb08f2
Compare
The individual fields don't necessarily need to have any particular size or alignment for this to work, though if they're larger than 4 bytes (as the array fields are) or not aligned to 4 bytes, the plugin might see some bytes from before a shared write and some bytes from after it within the same field. That might cause undefined behavior if certain bit representations don't correspond to valid values for any of the fields in I hadn't considered the possibility that For common desktop platforms (and mobile platforms as well), none of these C++ implementation-based edge cases should happen. I can find examples of code in prominent projects that assumes the pointer returned by I'll make the changes I think make sense to address this stuff and push them so you can see what you think. |
7c6c27b
to
205d47f
Compare
Sorry for all the force pushes. |
Force pushes are the correct way to do this. |
205d47f
to
4765b27
Compare
5c6a6a6
to
8b5d46b
Compare
Are you referring to this quote from the docs?
if so, then this would not be a problem for us as we don't care about the values of padding bits anyway. |
b2bc4e7
to
9336d8e
Compare
I'm referring to this part:
It sounds like making an |
9336d8e
to
054fe04
Compare
To me read reads as merely yielding an indeterminate value - aka: it is guaranteed to yield some random int, but we can't know which (even if we know the source bit pattern it is copied from). But for us this doesn't matter as all possible 4 byte bit patterns are valid unsigned 32-bit integer representations and therefore, we shouldn't have to worry about what exactly we are copying (and since padding bits will only end up as padding bits again, we indeed don't care about their values) |
054fe04
to
0b15165
Compare
It says behavior is undefined if the smallest object containing any indeterminate bit isn't |
Oh yeah indeed. On the other hand though, I can't imagine that we have this kind of issue with |
The Link plugin uses an inherently racy protocol to communicate with applications: shared memory with no means of synchronization. This commit makes no changes to this protocol and shouldn't break anything that was working before. That means it doesn't eliminate race conditions, but it does allow the plugin to work without the risk of *data races* specifically, which are undefined behavior. This is done by using 32-bit atomic operations to copy the LinkedMem struct out of shared memory before reading from it. This should work well, since every field of LinkedMem has a size that's a multiple of 32 bits, and 32-bit atomics are widely supported. With this change, applications can avoid data races with the Link plugin by also accessing shared memory exclusively with 32-bit atomic operations. Applications that already work with the plugin should continue to work.
SharedMemory is only used to point to an instance of LinkedMem. Preventing it from having a dynamic size simplifies the code.
0b15165
to
6647cbd
Compare
Yeah, it's really hard to say without a copy of the C++14 standard. I also don't know what happens when you write an indeterminate value to an atomic. I changed the comment to say "possible undefined behavior." Any other comments or changes to suggest? |
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.
LGTM - let's see how it'll work out in practice :)
Thanks for your contribution and your patience :D |
💚 All backports created successfully
Questions ?Please refer to the Backport tool documentation and see the Github Action logs for details |
The Link plugin uses an inherently racy protocol to communicate with applications: shared memory with no means of synchronization. This commit makes no changes to this protocol and shouldn't break anything that was working before. That means it doesn't eliminate race conditions, but it does allow the plugin to work without the risk of data races specifically, which are undefined behavior.
This is done by using 32-bit atomic operations to copy the LinkedMem struct out of shared memory before reading from it. This should work well, since every field of LinkedMem has a size that's a multiple of 32 bits, and 32-bit atomics are widely supported.
With this change, applications can avoid data races with the Link plugin by also accessing shared memory exclusively with 32-bit atomic operations. Applications that already work with the plugin should continue to work.
This is marked as a "fix," but as far as I know, the bugs it fixes are only hypothetical right now, so I'm offering it for your consideration.
Checks