SD_EVENT_ADD_DEFER(3)

πŸ’… SD_EVENT_ADD_DEFER β€” sd_event_add_defer, sd_event_add_post, sd_event_add_exit, sd_event_handler_t

okay bestie, so this is the sd_event_add_defer(3) page from the sd_event_add_defer manual β€” we're talking systemd's event loop, and honestly these three functions are the main character energy of "do this thing at this moment in the loop." static event sources. no cap. let's get into it πŸ¦‹


✨ NAME ✨

sd_event_add_defer, sd_event_add_post, sd_event_add_exit, sd_event_handler_t β€” these are the functions that add static event sources to an event loop. that's it, that's the whole vibe πŸŽ€


✨ SYNOPSIS ✨

#include <systemd/sd-event.h>

typedef struct sd_event_source sd_event_source;

typedef int (*sd_event_handler_t)(sd_event_source *s, void *userdata);

int sd_event_add_defer(sd_event *event, sd_event_source **source,
                       sd_event_handler_t handler, void *userdata);

int sd_event_add_post(sd_event *event, sd_event_source **source,
                      sd_event_handler_t handler, void *userdata);

int sd_event_add_exit(sd_event *event, sd_event_source **source,
                      sd_event_handler_t handler, void *userdata);

πŸ’– DESCRIPTION πŸ’–

so these three cuties all add a new static event source to an event loop. same shape every time:

  • the event loop object? that's the event parameter πŸ’«
  • the event source object comes back to you in the source parameter.

the event sources are enabled statically and they'll "fire" when you actually run the event loop and the conditions described below get met. πŸ”₯

the handler is a function to call β€” or NULL. your handler gets handed the userdata pointer, and userdata is literally whatever you want, caller's choice, go off 🫢. the handler may return negative to signal an error (more on that below); any other return values are just ignored, like, not even mad. and if handler is NULL, a default handler that calls sd_event_exit(3) gets used.

🌸 sd_event_add_defer()

adds a new event source that gets dispatched instantly β€” before the event loop goes to sleep again and waits for new events. by default the handler gets called once (SD_EVENT_ONESHOT).

⚠️ okay real talk: if you set the event source to SD_EVENT_ON, the event loop will never go to sleep again and will continuously call the handler, possibly interleaved with other event sources. that's a hot loop, bestie. be so for real about that. πŸ’€

πŸ¦‹ sd_event_add_post()

adds a new event source that runs before the event loop sleeps and waits for new events β€” but only after at least one other non-post event source was dispatched. by default this source is enabled permanently (SD_EVENT_ON).

πŸ™‚β€β†•οΈ note that this event source type will still let the event loop go to sleep again, even if set to SD_EVENT_ON, as long as no other event source is ever triggered. so it's chiller than it sounds.

πŸŽ€ sd_event_add_exit()

adds a new event source that gets dispatched when the event loop is terminated with sd_event_exit(3). that's its whole thing. iconic, honestly.


πŸ’… enabling / disabling

the sd_event_source_set_enabled(3) function is your girl for this β€” use it to enable the event source permanently (SD_EVENT_ON) or make it fire just once (SD_EVENT_ONESHOT).

and if the handler function returns a negative error code, one of two things happens:

  • it gets disabled after the invocation, even if SD_EVENT_ON mode was requested before, or
  • it causes the loop to terminate.

see sd_event_source_set_exit_on_failure(3) for the details on that. ⭐

🧚 destroying a source

to destroy an event source object, use sd_event_source_unref(3) β€” but heads up, the event source is only removed from the event loop when all references to it are dropped. so like, unref alone isn't enough if someone else is holding it.

to make sure an event source doesn't fire anymore even when there's still a reference to it kept, consider setting the event source to SD_EVENT_OFF with sd_event_source_set_enabled(3). πŸ‘‘

πŸ™ˆ the NULL source param

if the second parameter of these functions is passed as NULL, no reference to the event source object is returned. in that case, the event source is considered "floating", and will be destroyed implicitly when the event loop itself is destroyed. cute, low maintenance, self-cleaning ✨

😭 the NULL handler + exit code thing

if the handler parameter to sd_event_add_defer() or sd_event_add_post() is NULL, and the event source fires, this is considered a request to exit the event loop. in that case, the userdata parameter β€” cast to an integer β€” is passed as the exit code parameter to sd_event_exit(3).

πŸ’€ similar functionality is not available for sd_event_add_exit(), because these types of event sources are only dispatched when exiting anyway. it's already doing the thing, bestie, no notes.

🌈 RETURN VALUE 🌈

on success, these functions return 0 or a positive integer. on failure, they return a negative errno-style error code. periodt.

🌸 Errors

returned errors may indicate the following problems:

  • -ENOMEM β€” not enough memory to allocate an object. 😭
  • -EINVAL β€” an invalid argument has been passed. πŸ™ˆ
  • -ESTALE β€” the event loop is already terminated. πŸ’€
  • -ECHILD β€” the event loop has been created in a different process, library or module instance. 🫠

⭐ NOTES ⭐

functions described here are available as a shared library, which can be compiled against and linked 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... sharing is fine, just not simultaneously 😀

the code described here uses getenv(3), which is declared to be not multi-thread-safe. this means the code calling the functions described here must not call setenv(3) from a parallel thread.

⚠️ recommendation from the manpage gods: only do calls to setenv() from an early phase of the program when no other threads have been started. seriously, don't be messy about this.

πŸ¦‹ HISTORY πŸ¦‹

sd_event_add_defer(), sd_event_add_post(), sd_event_add_exit(), and sd_event_handler_t() were added in version 217. vintage. retro. still slaying. πŸ’œ


πŸ’– SEE ALSO πŸ’–

systemd(1), sd-event(3), sd_event_new(3), sd_event_now(3), sd_event_add_io(3), sd_event_add_time(3), sd_event_add_signal(3), sd_event_add_child(3), sd_event_add_inotify(3), sd_event_source_set_enabled(3), sd_event_source_set_priority(3), sd_event_source_set_userdata(3), sd_event_source_set_description(3), sd_event_source_set_floating(3), sd_event_exit(3)


and that's the whole page, bestie 🫢 this was systemd 261.3, manual page SD_EVENT_ADD_DEFER(3) β€” go forth and defer your events responsibly, mwah πŸ’‹βœ¨

πŸ“¦ where this page comes from