SD_BUS_MESSAGE_NEW(3)

πŸŽ€ NAME πŸŽ€

okay so this is the page for sd_bus_message_new πŸ’– β€” and it's basically the whole "make a bus message, hold onto it, let it go" saga. Here's everyone invited to this party:

  • sd_bus_message_new
  • sd_bus_message_ref
  • sd_bus_message_unref
  • sd_bus_message_unrefp
  • SD_BUS_MESSAGE_METHOD_CALL
  • SD_BUS_MESSAGE_METHOD_RETURN
  • SD_BUS_MESSAGE_METHOD_ERROR
  • SD_BUS_MESSAGE_SIGNAL
  • sd_bus_message_get_bus

and together they create a new bus message object and create or destroy references to it. that's the whole vibe ✨


✨ SYNOPSIS ✨

#include <systemd/sd-bus.h>

enum {
      SD_BUS_MESSAGE_METHOD_CALL,
      SD_BUS_MESSAGE_METHOD_RETURN,
      SD_BUS_MESSAGE_METHOD_ERROR,
      SD_BUS_MESSAGE_METHOD_SIGNAL,
};

int sd_bus_message_new(sd_bus *bus, sd_bus_message **m, uint8_t type);

sd_bus_message *sd_bus_message_ref(sd_bus_message *m);

sd_bus_message *sd_bus_message_unref(sd_bus_message *m);

void sd_bus_message_unrefp(sd_bus_message **mp);

sd_bus *sd_bus_message_get_bus(sd_bus_message *m);

πŸ’… DESCRIPTION πŸ’…

so sd_bus_message_new() makes a brand new bus message object, attaches it to the bus bus, and hands it back to you in the output parameter m. 🫢 this object is reference-counted, meaning it gets destroyed once every single reference is gone. at the start, you, the caller, own the one and only reference to it. and heads up β€” the message object holds a reference to the bus object, so that bus object is not going anywhere as long as the message is still alive. iconic mutual-support behaviour, honestly πŸ’–

lowkey important note: this is a low-level call. like, it's the bare metal version. in most cases you're gonna have a way better time with the functions that create a message of a certain type and initialize all the various fields for you β€” that's sd_bus_message_new_method_call(3), sd_bus_message_new_method_error(3), sd_bus_message_new_method_return(3), and sd_bus_message_new_signal(3). they're easier, they're convenient, they ate πŸ’…

the type parameter tells everyone what kind of message this is. it has to be exactly one of these four besties:

  • SD_BUS_MESSAGE_METHOD_CALL β€” a method call πŸ“ž
  • SD_BUS_MESSAGE_METHOD_RETURN β€” a method call reply πŸ’Œ
  • SD_BUS_MESSAGE_METHOD_ERROR β€” an error reply to a method call 😭
  • SD_BUS_MESSAGE_SIGNAL β€” a broadcast message with no reply πŸ“’

the flag that allows interactive authorization gets initialized from whatever value is currently set on the bus object β€” peep sd_bus_set_allow_interactive_authorization(3) for that. and yeah, you can change it later with sd_bus_message_set_allow_interactive_authorization(3). ✨

sd_bus_message_ref() bumps the internal reference counter of m up by one. πŸ”₯

sd_bus_message_unref() drops the internal reference counter of m down by one. once that count hits zero the message object is destroyed and cannot be used anymore, so calling sd_bus_message_ref() or sd_bus_message_unref() on it after that is illegal. not "rude", not "frowned upon" β€” illegal πŸš«πŸ’€

sd_bus_message_unrefp() is like sd_bus_message_unref() but it takes a pointer to a pointer to an sd_bus_message object. this one is your bestie when you're pairing it with GCC's and LLVM's Clean-up Variable Attribute[1]. if you want to see an example of how to use the cleanup attribute, go look at sd_bus_new(3). 🧚

about those NULL cases, because this matters:

  • sd_bus_message_ref() and sd_bus_message_unref() execute no operation if the passed-in bus message object address is NULL.
  • sd_bus_message_unrefp() will first dereference its argument, which must not be NULL, and will execute no operation if that is NULL.

sd_bus_message_get_bus() returns the bus object that message m is attached to. 🚌


🌸 RETURN VALUE 🌸

if everything slays, sd_bus_message_new() returns 0 or a positive integer. if it doesn't, you get a negative errno-style error code. 😭

sd_bus_message_ref() always returns the argument. periodt.

sd_bus_message_unref() always returns NULL.

sd_bus_message_get_bus() always returns the bus object.

🫢 Errors

the errors you might get back mean the following things:

  • -EINVAL β€” the specified type is invalid. πŸ™ˆ
  • -ENOTCONN β€” the bus parameter bus is NULL, or the bus is not connected. πŸ”Œ
  • -ENOMEM β€” memory allocation failed. πŸ’€

πŸ¦‹ 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. πŸŽ€

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, and multiple independent objects may be used from different threads in parallel. so like, share the object, but take turns βœ‹πŸŒˆ

⚠️ caveat time: 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 recommendation is to only do your setenv() calls in an early phase of the program, back when no other threads have been started yet. do it before the group chat gets going, iykyk πŸ’…

πŸ‘‘ HISTORY πŸ‘‘

sd_bus_message_new(), sd_bus_message_ref(), sd_bus_message_unref(), sd_bus_message_unrefp(), and sd_bus_message_get_bus() were added in version 240. πŸ‘‘βœ¨


🌈 SEE ALSO 🌈

systemd(1), sd-bus(3), sd_bus_new(3), sd_bus_message_new_method_call(3), sd_bus_message_new_method_error(3), sd_bus_message_new_method_return(3), sd_bus_message_new_signal(3)


⭐ NOTES ⭐

the little footnote one πŸ“

  1. Clean-up Variable Attribute β€” https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html

and that's the whole page, bestie 🫢 this was systemd 261.3, SD_BUS_MESSAGE_NEW(3), and you absolutely understood all of it. go forth and reference-count responsibly πŸ’–πŸŽ€βœ¨

πŸ“¦ where this page comes from