Hi Stanislav,

On Mon, Mar 4, 2019 at 9:56 PM Stanislav Angelovič
<[email protected]> wrote:
>
> Hi sd-bus-ers!
>
> Quick question: How can I process a method call on service side in a 
> different thread, without creating race condition?
>
> Longer version:
>
> In sdbus-c++, we are working on server-side asynchronous method call support.
>
> In sd-bus, a service handles D-Bus method calls via sd_bus_message_handler_t 
> callback that is registered during object vtable registration. The callback 
> receives sd_bus_message* as the first parameter (among others), which is the 
> method call message. In a typical implementation, this method call is served 
> synchronously (D-Bus method parameters are deserialized from the message, an 
> operation is executed, and either method reply or method error, depending on 
> the condition, is sent back) and the callback returns execution to sd-bus. 
> Standard stuff so far.
>
> Now, I would like to handle the method call asynchronously, in a thread pool. 
> So a typical approach would be to increment ref count of sd_bus_message and 
> push the sd_bus_message* in a queue. It would then be popped by one of worker 
> threads and processed -- method parameters are deserialized, method logic is 
> executed, and either method reply or method error is created and sent back, 
> and sd_bus_message* ref count is decremented. Now, sending back the reply or 
> an error is thread-safe in my implementation, I don't have an issue with 
> that. The problem that I want to discuss is the method call sd_bus_message 
> instance. I cannot simply forward a pointer to it to a separate thread, 
> because of it's non-atomic ref count handling, which is the source of race 
> condition (hopefully this is the only data race condition here). It's 
> manipulated by both the D-Bus loop thread (which decrements ref count after 
> sd_bus_message_handler_t returns) and the worker thread concurrently (which 
> also decrements ref count after it has handled the method call).
>
> I see three potential solutions now:
>
> 1. In sd_bus_message_handler, create a deep copy of the method call 
> sd_bus_message via sd_bus_message_copy(). And pass a pointer to this copy to 
> a worker thread. This is very straight-forward and simple, it solves the race 
> condition, but introduces a performance cost of copying (I don't know how big 
> this cost is, perhaps it's rather negligible).
>
> 2.  Don't pass the sd_bus_message* to the worker thread. In 
> sd_bus_message_handler, rather deserialize all arguments, create (empty) 
> method reply message, and move these to the worker thread. The worker thread 
> executes the logic and serializes results to that reply message, and sends it 
> back. The problem here is that we have to create a method reply or method 
> error before the fact (before executing method logic), which in case of 
> method error is impossible because we don't know possible error name and 
> message beforehand.
>
> 3. Solution on sd-bus side :-) which is to make sd_bus_message ref count 
> handling thread-safe (atomic), just like one for sd_bus. This avoids the need 
> for deep copy. What do you think? Anyway, we'd still have to come up with a 
> solution now, based on already releases sd-bus versions.
>
> So the only feasible solution for now seems to be #1 (while #3 could also be 
> a sd-bus improvement for the future). Do you agree that this is the good way 
> along the lines of sd-bus design principles, or are there more options I'm 
> unaware of?
>

In my use of sdbus I am going for option 3. Also because I am not sure
what happens when sdbus writes on the bus in parallel two long
messages. I know that sdbus is thread aware, but not thread safe.
So 2 long messages could in theory be sent in collision. Maybe you can
verify this opening two (or more) instances of a client that query
automatically all introspectable methods of a specific server
implemented with your thread pool, and see what happens in repeated
trials.

> Thank you for your constructive comments, and sorry for long elaboration :) I 
> wanted to be clear...
>
> Cheers,
> Stanislav.
>

Cheers,
Giaciinto


> _______________________________________________
> systemd-devel mailing list
> [email protected]
> https://lists.freedesktop.org/mailman/listinfo/systemd-devel
_______________________________________________
systemd-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/systemd-devel

Reply via email to