[systemd-devel] sd-bus delayed reply

Lennart Poettering lennart at poettering.net
Mon Jan 28 10:54:49 UTC 2019


On Mo, 28.01.19 12:25, Jean Valjean (valjean.jean1802 at gmail.com) wrote:

> Is there a possibility to send a delayed response to a method call?

Yes. Just keep a reference to the incoming method call message object
around, and then, when you are ready to respond, respond.

> The scenario is
> 1. Message A with input data is received by a service and placed into
> a list. This message will be used to reply later.
> 2. A routine is invoked that might take a long time to prepare a reply
> on a background thread
> 3. While reply is being prepared service can still receive and process
> new incoming messages B, C, D and send replies to them
> 4. Once routine is done A is taken from the list and used to send a reply.
>
> I know that it is possible to use sd_bus_process to get and process
> incoming messages.
> But in that case I wonder how do I add an object so that it is visible
> in the tree produced by
> busctl --user tree org.example
> I can't use sd_bus_add_object or sd_bus_add_object_vtable because If I
> execute the routine in handlers then
> it will block the service from receiving other messages.

I am not sure I follow what precisely you are trying to do, but note
that sd-bus is not supposed to be dispatched recursively, i.e. you
cannot run the sd-bus event loop from inside the sd-bus event loop if
you follow what I mean.

Hence, when you want to do what you are trying to do the usual
approach is to run a top-level event loop (i.e. sd-event or glib or
any other you like), then when you get the incoming method call, you
initiate your long-running action, and quickly return to the event
loop so that the event loop can continue to process further
events. And then when you are done you respond to the message you kept
a reference on.

Now, you might wonder how to "initiate your long-running action" while
at the same time "quickly returning to the event loop". You have
multiples options there. You can either do threads (i.e. pass of the
long-running work to another worker thread, which then reports
completion back to the main event loop — maybe through a pipe() —
which can then reply to the message), or in many cases you can split
up your work in shorter units that can run from separate
low-priorized event loop handlers (in sd-event for example in "defer"
event loops running at a low priority), and then run everything from
the same event loop. I personally usually go for the latter, but it
comes with its own complexities.

Lennart

--
Lennart Poettering, Red Hat


More information about the systemd-devel mailing list