SD_BUS_CALL(3)
π
SD_BUS_CALL(3) β aka sd_bus_call, sd_bus_call_async
okay so bestie, welcome to sd_bus_call(3), a page straight out of systemd and honestly it's giving core D-Bus communication energy. this is the page where you learn how to actually invoke a D-Bus method call β sync or async, your choice, main character energy either way π
β¨
πΈ NAME πΈ
sd_bus_call, sd_bus_call_async β literally just "Invoke a D-Bus method call". that's it. that's the whole vibe. π
β¨ SYNOPSIS β¨
#include <systemd/sd-bus.h>
typedef int (*sd_bus_message_handler_t)(sd_bus_message *m,
void *userdata,
sd_bus_error *ret_error);
int sd_bus_call(sd_bus *bus, sd_bus_message *m, uint64_t usec,
sd_bus_error *ret_error, sd_bus_message **reply);
int sd_bus_call_async(sd_bus *bus, sd_bus_slot **slot,
sd_bus_message *m,
sd_bus_message_handler_t callback, void *userdata,
uint64_t usec);
yes, that typedef is a function pointer and yes it's iconic. don't be scared of it π¦
π DESCRIPTION π
so sd_bus_call() takes a complete bus message object and calls the corresponding D-Bus method. on success, the response gets stored in reply. π usec is your timeout, measured in microseconds (yes microseconds, not milliseconds, read it again bestie). and if ret_error is not NULL and sd_bus_call() fails β whether because of an internal error or because it received a D-Bus error reply β then ret_error gets initialized to an instance of sd_bus_error describing the error. no cap. π«Ά
sd_bus_call_async() is like sd_bus_call() but it works asynchronously β she doesn't wait around, she's got things to do. the callback tells it which function to call when the response arrives. the userdata pointer gets passed to the callback function, and you may choose it freely, it's your little gift to your future self π. if slot is not NULL and sd_bus_call_async() succeeds, slot is set to a slot object which can be used to cancel the method call at a later time using sd_bus_slot_unref(3). if slot is NULL, the lifetime of the method call is bound to the lifetime of the bus object itself, and it cannot be cancelled independently β so like, it's stuck there, attached, lowkey clingy. see sd_bus_slot_set_floating(3) for the details on that. πͺ
callback is called when a reply arrives, with the reply, userdata, and an sd_bus_error output parameter as its arguments. and here's the plot twist π«’ β unlike sd_bus_call(), the sd_bus_error output parameter passed to the callback will be empty. so how do you know if the call actually worked? use sd_bus_message_is_method_error(3) on the reply message passed to the callback instead. that's the vibe check. β
now the handler-chaining rules, pay attention:
- if the callback returns zero and the
sd_bus_erroroutput parameter is still empty when the callback finishes, other handlers registered with functions such assd_bus_add_filter(3)orsd_bus_add_match(3)are given a chance to process the message π - if the callback returns a non-zero value, or the
sd_bus_erroroutput parameter is not empty when the callback finishes, no further processing of the message is done. done. periodt. π
generally you want to return zero from the callback to give other registered handlers a chance to process the reply as well. sharing is caring fr fr π
π lil note that trips everyone up: the sd_bus_error parameter is an output parameter of the callback function, not an input parameter. it can be used to propagate errors from the callback handler β it will not receive any error that was received as method reply. iykyk.
the message m passed to the callback is only borrowed β meaning the callback should not call sd_bus_message_unref(3) on it, ok? hands off, it's not yours π«. if the callback wants to hold on to the message beyond the lifetime of the callback, it needs to call sd_bus_message_ref(3) to create a new reference. that's how you keep it π
and if usec is zero, the default D-Bus method call timeout is used. see sd_bus_get_method_call_timeout(3) π
π₯ RETURN VALUE π₯
on success, these functions return a non-negative integer. on failure, they return a negative errno-style error code. simple as that, bestie π
π Errors π
when sd_bus_call() internally receives a D-Bus error reply, it will set ret_error if it is not NULL, and will return a negative value mapped from the error reply β see sd_bus_error_get_errno(3).
returned errors may indicate the following problems:
-EINVALβ one of these situations, and there are a bunch π« :- the input parameter
misNULL. - the input parameter
mis not a D-Bus method call. to create a new D-Bus method call, usesd_bus_message_new_method_call(3). - the input parameter
mhas theBUS_MESSAGE_NO_REPLY_EXPECTEDflag set. - the input parameter
erroris non-NULLbut was not set toSD_BUS_ERROR_NULL.
- the input parameter
-ECHILDβ the bus connection was allocated in a parent process and is being reused in a child process afterfork(). awkward π¬-ENOTCONNβ the input parameterbusisNULL, or the bus is just not connected. she's offline π-ECONNRESETβ the bus connection was closed while waiting for the response. ghosted π₯-ETIMEDOUTβ a response was not received within the given timeout. the silence was loud π-ELOOPβ the messagemis addressed to its own client. bestie called herself π-ENOMEMβ memory allocation failed. the storage said no π
π§ NOTES π§
the functions described here are available as a shared library, which can be compiled against and linked to with the libsystemd pkg-config(1) file. compile and link, that's the whole ritual β¨
all functions listed here are thread-agnostic and only a single thread may operate on a given object at any given time. different threads may access the same object at different times. multiple independent objects may be used from different threads in parallel. so like, take turns, it's not that hard π
the code described here uses getenv(3), which is declared to be not multi-thread-safe. this means that the code calling the functions described here must not call setenv(3) from a parallel thread. it is recommended to only do calls to setenv() from an early phase of the program when no other threads have been started. do the env stuff first, then party π
β HISTORY β
sd_bus_call() and sd_bus_call_async() were added in version 221. vintage but make it fashion π
π SEE ALSO π
systemd(1), sd-bus(3), sd_bus_call_method(3), sd_bus_call_method_async(3), sd_bus_message_new_method_call(3), sd_bus_message_append(3), sd_bus_error(3)
and that's the whole page bestie β you ate that π
π this cutie was brought to you by systemd 261.3, manual page SD_BUS_CALL(3), and it's signing off with a little sparkle π¦β¨π
π¦ where this page comes from
- ubuntu stonking: libsystemd-dev 261.3-0ubuntu3 Β· LGPL-2.1-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms