SD_EVENT_GET_FD(3)
π SD_EVENT_GET_FD β okay bestie, let's get you that file descriptor
So this is the sd_event_get_fd page from the sd-event corner of the systemd manual universe, and honestly? It's a little bop. Let's go.
β¨ NAME β¨
sd_event_get_fd β obtain a file descriptor to poll for event loop events π
π¦ SYNOPSIS π¦
#include <systemd/sd-event.h>
int sd_event_get_fd(sd_event *event);
πΈ DESCRIPTION πΈ
Okay so picture this: sd_event_get_fd() hands you back the file descriptor that an event loop object (the kind you got from sd_event_new(3)) uses to wait for events. That's it, that's the whole vibe. β¨
And the iconic part? You can poll that file descriptor itself for POLLIN/EPOLLIN events. Which means β drumroll β you can literally embed an sd-event(3) event loop inside another event loop, even a foreign one. Crossover episode fr fr. π«Ά
Now, heads up: the file descriptor you get back refers to an epoll(7) object. And the recommendation is don't go altering it by invoking epoll_ctl(2) on it, because you'll mess with the event loop's inner logic and all of its little assumptions. Not the move. π
π RETURN VALUE π
On success, sd_event_get_fd() returns a non-negative file descriptor. Slay. On failure, it returns a negative errno-style error code. π
π Errors
Returned errors may indicate the following problems:
-EINVALβ event is not a valid pointer to ansd_eventstructure. Like, not a real one. π-ECHILDβ The event loop has been created in a different process, library or module instance. Wrong family, bestie.
π EXAMPLES π
Example 1. Integration in the GLib event loop β the crossover nobody asked for but everybody needed π₯
/* SPDX-License-Identifier: MIT-0 */
#include <stdlib.h>
#include <glib.h>
#include <systemd/sd-event.h>
typedef struct SDEventSource {
GSource source;
GPollFD pollfd;
sd_event *event;
} SDEventSource;
static gboolean event_prepare(GSource *source, gint *timeout_) {
sd_event *event = ((SDEventSource *) source)->event;
/* GLib does not guarantee that check() is always called between two
* consecutive prepare() invocations. For example, if another thread
* attaches/removes a source with poll fds to this GMainContext while
* the main thread is inside poll(), g_main_context_check_unlocked()
* returns immediately without calling any source's check().
*
* If check() was skipped, the sd_event is still in SD_EVENT_ARMED
* state. Return FALSE to let the normal poll() -> check() -> dispatch()
* path complete the cycle. */
if (sd_event_get_state(event) == SD_EVENT_ARMED)
return FALSE;
return sd_event_prepare(event) > 0;
}
static gboolean event_check(GSource *source) {
return sd_event_wait(((SDEventSource *)source)->event, 0) > 0;
}
static gboolean event_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) {
return sd_event_dispatch(((SDEventSource *)source)->event) > 0;
}
static void event_finalize(GSource *source) {
sd_event_unref(((SDEventSource *)source)->event);
}
static GSourceFuncs event_funcs = {
.prepare = event_prepare,
.check = event_check,
.dispatch = event_dispatch,
.finalize = event_finalize,
};
GSource *g_sd_event_create_source(sd_event *event) {
SDEventSource *source;
source = (SDEventSource *)g_source_new(&event_funcs, sizeof(SDEventSource));
source->event = sd_event_ref(event);
source->pollfd.fd = sd_event_get_fd(event);
source->pollfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
g_source_add_poll((GSource *)source, &source->pollfd);
return (GSource *)source;
}
π§ NOTES π§
The functions described here are available as a shared library, which you can compile against and link to with the libsystemd pkg-config(1) file. Very demure, very linkable. π
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. It's giving "sharing is caring but read the room." π
β Real talk though: the code described here usesgetenv(3), which is declared to be not multi-thread-safe. Which means any code calling the functions described here must not callsetenv(3)from a parallel thread. The recommendation is to only do yoursetenv()calls from an early phase of the program, when no other threads have been started yet. Do it before the group chat gets going. π«Ά
π°οΈ HISTORY π°οΈ
sd_event_get_fd() was added in version 217. An icon, a legend, a moment in time. β¨
π SEE ALSO π
sd-event(3), sd_event_new(3), sd_event_wait(3), epoll_ctl(2), epoll(7)
Okay that's the whole page, you ate it up, no crumbs. π This one's from the systemd 261.3 era β go forth and poll responsibly, bestie. π¦πΈ
π¦ 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