-
Notifications
You must be signed in to change notification settings - Fork 138
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
*mut bpf_object
cannot be sent between threads safely
#245
Comments
I think it's send-able (able to be used by 2 threads at different times) but not sync-able (able to be used by 2 threads at the same time). @anakryiko does this sound accurate to you? |
What about |
I think it would be helpful to have some kind of overview what synchronization assumptions libbpf C types make, but I couldn't find all that much information about that in the libbpf documentation: https://libbpf.readthedocs.io/en/latest/search.html?q=thread-safe&check_keywords=yes&area=default If we assume that everything that is not thread safe is marked as such (and everything with no mention of thread-safety is safe to be used), we could at least add @anakryiko, do you know if the above assumption is correct? Also, and I am happy to bring this up more publicly in libbpf itself, perhaps it would be helpful to highlight these properties in terms of "POSIX Safety Concepts" more prominently, as seems to be a common thing for many POSIX functions (and beyond?)? |
Okay, I wanted to change this too, so I did some digging. Turns out the answer is: it's complicated. The goal would be to prove this is okay: unsafe impl Send for Object {}
unsafe impl Sync for Object {} for
One final overarching point that I omitted though that's quite important is that I ignored the side effects of |
I spoke with anakryiko (the
So Andrii's stance seems to be that aligned pointer reads and writes are always atomic and so there is no issue. Personally, I think it should be an explicit atomic read and write, but I guess whatever. That reasoning would then presumably also apply to |
From what I could gather, there are two meanings for "atomic" which creates ambiguity and confusion. Aligned pointer reads and writes are atomic in the sense that no thread will ever observe a "torn value" (half the bit pattern changed but the other half has not changed yet), it just writes the new value at once. It doesn't however mean that the caches of other processors will be invalidated such that they will see the new value any time soon, which effectively means that static int i = -1;
if (i < 0) {
i = some_check() == 0;
return i == 1; does not prevent If writes to This blog post explained it pretty well |
I agree though that trying to make it |
Yeah, the two are often mixed together. However, I believe it is a property of the higher level logic built on top whether when another CPU sees a value as being updated has a bearing on correctness. That's different from the correctness aspect that is whether it can only see coherent values. In our case, I argue, the former does not matter. Clients/users cannot have any expectation of a
To
( So in our case, the writes we are concerned about really would map to
To the degree I can tell, Go hides memory orderings from developers (see above). Furthermore, the package provides an abstraction that is guaranteed to ensure atomicity for various types, including those not being of the machine's native word size (such as |
there is no need to fight a fight, someone just has to send a patch switching to atomic exchange. No one yet complained about this, so no one did the work. As for the issue at hands. I agree with @danielocfb , these APIs are not unsafe, and shouldn't be forced onto users to use explicit unsafe blocks. |
Is it intentional that structs like
WlistSkel
don't implementSend
andSync
? Because they contain raw pointers, they're automatically marked as non-Send
able and non-Sync
hronized, but is it actually the case that one cannot use the data structures from multiple threads?I'm trying to build a HTTP API around libbpf, and
warp
wants to use multiple threads to handle HTTP requests, thus the types would need to be shareable between threads. Otherwise, I'd have to spawn a separate thread that serializes and handles all the communication with libbpf, which would be less efficient.Errors look like this:
The text was updated successfully, but these errors were encountered: