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:

  1. poll the file descriptor returned by sd_bus_get_fd()
  2. for the events indicated by sd_bus_get_events()
  3. 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:


πŸ¦‹ 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 after fork(). 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 using sd_bus_set_fd(), which sd_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 uses getenv(3), which is declared to be not multi-thread-safe. that means any code calling the functions described here must not call setenv(3) from a parallel thread. the recommended move is to only call setenv() 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