SD_BUS_GET_FD(3)
π sd_bus_get_fd β get the fd, the events and the timeout from your bus object
okay so this is the sd_bus_get_fd(3) page from the sd_bus_get_fd manual, bestie, and it's basically your cheat sheet for hooking a D-Bus connection into your own event loop. no cap, this is the good stuff π¦
β¨ NAME β¨
sd_bus_get_fd, sd_bus_get_events, sd_bus_get_timeout β the three besties that tell you which file descriptor to watch, which I/O events to wait for, and how long to wait for them, all on a message bus object. π
πΈ SYNOPSIS πΈ
#include <systemd/sd-bus.h>
int sd_bus_get_fd(sd_bus *bus);
int sd_bus_get_events(sd_bus *bus);
int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec);
π DESCRIPTION π
the three icons π
sd_bus_get_fd() hands you back the file descriptor your message bus object uses to talk to the world. you can feed that fd straight into poll(3) (or literally any similar function) to wait for I/O events on the bus connection object. and here's the cute detail: if the bus object was set up with sd_bus_set_fd(), then the input_fd file descriptor you passed in that call is exactly what comes back out. π«Ά
sd_bus_get_events() tells you which I/O events you should be waiting for β like, the ones that go straight into poll() or a similar call. it returns a combination of POLLIN, POLLOUT, β¦ events, or a negative value if something went wrong. β
sd_bus_get_timeout() returns the absolute timeout in ΞΌs, and from that you derive the relative timeout you hand to poll() (or a similar call) when you're waiting for events on your bus connection. some notes on that returned timeout, because it has β¨layersβ¨:
- it may be zero β in which case the next I/O polling call should be invoked in non-blocking mode πβοΈ
- it may be
UINT64_MAXβ in which case the I/O polling call may block indefinitely, with no timeout applied at all π - the returned timeout is only a maximum sleeping time. it's totally permissible (and honestly even expected!) for the calling program to use shorter timeouts, in case other event sources are being polled in the same event loop. multitasking queen energy π
- the returned time-value is absolute, based on
CLOCK_MONOTONIC, and specified in microseconds
and when you convert that value to pass it as the third argument to poll() (which expects relative milliseconds), be careful, bestie π β convert it to a relative time and use a division that rounds up, so your I/O polling operation doesn't sleep for shorter than necessary. if you get that wrong you end up with unintended busy looping, which is giving "spinning CPU fan at 3am" and it's not the vibe. alternatively, just use ppoll(2) instead of plain poll() β it understands timeouts with nano-second granularity, so slay. π
how to actually use these π§
these three functions exist so you can hook a bus connection object up to an external or manual event loop built around poll() or a similar I/O polling call. before each invocation of the I/O polling call, you invoke all three:
- poll the file descriptor returned by
sd_bus_get_fd() - for the events indicated by
sd_bus_get_events() - and block for up to the timeout returned by
sd_bus_get_timeout()
after each I/O polling call, the bus connection needs to process incoming or outgoing data β do that by invoking sd_bus_process(3). π₯
heads up: these functions are only one of three supported ways to implement I/O event handling for bus connections. don't forget the other two exist π
alternatively:
- use
sd_bus_attach_event(3)to attach a bus connection to ansd-event(3)event loop π - use
sd_bus_wait(3)as a simple synchronous, blocking I/O waiting call π΄
π¦ RETURN VALUE π¦
sd_bus_get_fd()β on success, returns the file descriptor used for communication. on failure, a negative errno-style error code. πsd_bus_get_events()β on success, returns the I/O event mask to use for I/O event watching. on failure, a negative errno-style error code. β¨sd_bus_get_timeout()β on success, returns a non-negative integer. on failure, a negative errno-style error code. π
π Errors
the errors that come back may mean one of these things happened:
-EINVALβ an invalid bus object was passed. bestie, what even is that π-ECHILDβ the bus connection was allocated in a parent process and is being reused in a child process afterfork(). generational trauma fr fr π-ENOTCONNβ the bus connection has been terminated. it's gone. it left the chat. π₯-EPERMβ two distinct file descriptors were passed for input and output usingsd_bus_set_fd(), whichsd_bus_get_fd()cannot return. it literally cannot pick a favourite π«-ENOPKGβ the bus cannot be resolved. iykyk π
π NOTES π
these functions are available as a shared library, which you can compile against and link to with the libsystemd pkg-config(1) file. π¦
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, share the object, but not at the same time β consent and scheduling matter π
β οΈ the code described here usesgetenv(3), which is declared to be not multi-thread-safe. that means any code calling the functions described here must not callsetenv(3)from a parallel thread. the recommended move is to only callsetenv()from an early phase of the program, when no other threads have been started. do it before the group chat gets loud, okay? π§
β HISTORY β
sd_bus_get_fd(), sd_bus_get_events(), and sd_bus_get_timeout() were added in version 221. vintage icons only π
π SEE ALSO π
systemd(1), sd-bus(3), sd_bus_process(3), sd_bus_attach_event(3), sd_bus_wait(3), sd_bus_set_fd(3), poll(3)
and that's the whole page, bestie π«Ά this one shipped as part of systemd 261.3, filed under the SD_BUS_GET_FD(3) manual page β go forth and poll responsibly πβ¨
π¦ 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