[systemd-devel] sd-bus delayed reply
Jean Valjean
valjean.jean1802 at gmail.com
Mon Jan 28 12:00:04 UTC 2019
Can I, in principle, register objects and interfaces with
sd_bus_add_object_vtable like in
http://0pointer.net/blog/the-new-sd-bus-api-of-systemd.html
and in handler function, take a copy, of a reference to message
object, to global variable and use it later with
sd_bus_reply_method_return?
I tried to do that. But it seems, that when handler function returns,
it sends an error message to calling client if
sd_bus_reply_method_return
was not called inside handler.
In my event loop I will receive messages and then use something like
sd_bus_message_is_method_call to call appropriate handlers
or store reference to message and reply later. I my event loop I
basically call sd_bus_process to get messages.
A second parameter to sd_bus_process gives me message that I can store
and use to reply later.
But what about introspection? If i don't use sd_bus_add_object_vtable,
I can't use busctl or d-feet(GUI introspecting d-bus service),
to view what objects service provides and signatures for interfaces,
like was explained in a blog post I referenced above.
Boris
On Mon, 28 Jan 2019 at 12:54, Lennart Poettering <lennart at poettering.net> wrote:
>
> 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