diff options
| author | Michael Biebl <biebl@debian.org> | 2020-10-05 22:27:18 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2020-10-05 22:27:18 +0200 |
| commit | aafc1dbe4712c86189bbc1d4d54ad8cb4c69be7e (patch) | |
| tree | a2a9bb4d007339a0b1304540388230ccedac32bd /src/nm-dbus-object.c | |
| parent | e7b44ef4c80907346ec7492a09c45277459924fc (diff) | |
New upstream version 1.27.90 upstream/1.27.90
Diffstat (limited to 'src/nm-dbus-object.c')
| -rw-r--r-- | src/nm-dbus-object.c | 362 |
1 files changed, 200 insertions, 162 deletions
diff --git a/src/nm-dbus-object.c b/src/nm-dbus-object.c index a1332686..f49610ab 100644 --- a/src/nm-dbus-object.c +++ b/src/nm-dbus-object.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2018 Red Hat, Inc. */ @@ -8,64 +8,66 @@ #include "nm-dbus-object.h" #include "nm-dbus-manager.h" +#include "NetworkManagerUtils.h" /*****************************************************************************/ enum { - EXPORTED_CHANGED, + EXPORTED_CHANGED, - LAST_SIGNAL, + LAST_SIGNAL, }; -static guint signals[LAST_SIGNAL] = { 0 }; +static guint signals[LAST_SIGNAL] = {0}; -G_DEFINE_ABSTRACT_TYPE (NMDBusObject, nm_dbus_object, G_TYPE_OBJECT); +G_DEFINE_ABSTRACT_TYPE(NMDBusObject, nm_dbus_object, G_TYPE_OBJECT); /*****************************************************************************/ -#define _NMLOG_DOMAIN LOGD_CORE -#define _NMLOG(level, ...) __NMLOG_DEFAULT_WITH_ADDR (level, _NMLOG_DOMAIN, "dbus-object", __VA_ARGS__) +#define _NMLOG_DOMAIN LOGD_CORE +#define _NMLOG(level, ...) \ + __NMLOG_DEFAULT_WITH_ADDR(level, _NMLOG_DOMAIN, "dbus-object", __VA_ARGS__) -#define _NMLOG2_DOMAIN LOGD_DBUS_PROPS -#define _NMLOG2(level, ...) __NMLOG_DEFAULT_WITH_ADDR (level, _NMLOG2_DOMAIN, "properties-changed", __VA_ARGS__) +#define _NMLOG2_DOMAIN LOGD_DBUS_PROPS +#define _NMLOG2(level, ...) \ + __NMLOG_DEFAULT_WITH_ADDR(level, _NMLOG2_DOMAIN, "properties-changed", __VA_ARGS__) /*****************************************************************************/ static void -_emit_exported_changed (NMDBusObject *self) +_emit_exported_changed(NMDBusObject *self) { - g_signal_emit (self, signals[EXPORTED_CHANGED], 0); + g_signal_emit(self, signals[EXPORTED_CHANGED], 0); } static char * -_create_export_path (NMDBusObjectClass *klass) +_create_export_path(NMDBusObjectClass *klass) { - nm_assert (NM_IS_DBUS_OBJECT_CLASS (klass)); - nm_assert (klass->export_path.path); + nm_assert(NM_IS_DBUS_OBJECT_CLASS(klass)); + nm_assert(klass->export_path.path); #if NM_MORE_ASSERTS - { - const char *p; - - p = strchr (klass->export_path.path, '%'); - if (klass->export_path.int_counter) { - nm_assert (p); - nm_assert (p[1] == 'l'); - nm_assert (p[2] == 'l'); - nm_assert (p[3] == 'u'); - nm_assert (p[4] == '\0'); - } else - nm_assert (!p); - } + { + const char *p; + + p = strchr(klass->export_path.path, '%'); + if (klass->export_path.int_counter) { + nm_assert(p); + nm_assert(p[1] == 'l'); + nm_assert(p[2] == 'l'); + nm_assert(p[3] == 'u'); + nm_assert(p[4] == '\0'); + } else + nm_assert(!p); + } #endif - if (klass->export_path.int_counter) { - NM_PRAGMA_WARNING_DISABLE("-Wformat-nonliteral") - return g_strdup_printf (klass->export_path.path, - ++(*klass->export_path.int_counter)); - NM_PRAGMA_WARNING_REENABLE - } - return g_strdup (klass->export_path.path); + if (klass->export_path.int_counter) { + NM_PRAGMA_WARNING_DISABLE("-Wformat-nonliteral") + return g_strdup_printf(klass->export_path.path, ++(*klass->export_path.int_counter)); + NM_PRAGMA_WARNING_REENABLE + } + return g_strdup(klass->export_path.path); } /** @@ -83,26 +85,27 @@ _create_export_path (NMDBusObjectClass *klass) * Returns: the path @self was exported under */ const char * -nm_dbus_object_export (NMDBusObject *self) +nm_dbus_object_export(gpointer /* (NMDBusObject *) */ self) { - static guint64 id_counter = 0; + NMDBusObject * self1 = self; + static guint64 id_counter = 0; - g_return_val_if_fail (NM_IS_DBUS_OBJECT (self), NULL); + g_return_val_if_fail(NM_IS_DBUS_OBJECT(self1), NULL); - g_return_val_if_fail (!self->internal.path, self->internal.path); + g_return_val_if_fail(!self1->internal.path, self1->internal.path); - nm_assert (!self->internal.is_unexporting); + nm_assert(!self1->internal.is_unexporting); - self->internal.path = _create_export_path (NM_DBUS_OBJECT_GET_CLASS (self)); + self1->internal.path = _create_export_path(NM_DBUS_OBJECT_GET_CLASS(self1)); - self->internal.export_version_id = ++id_counter; + self1->internal.export_version_id = ++id_counter; - _LOGT ("export: \"%s\"", self->internal.path); + _LOGT("export: \"%s\"", self1->internal.path); - _nm_dbus_manager_obj_export (self); + _nm_dbus_manager_obj_export(self1); - _emit_exported_changed (self); - return self->internal.path; + _emit_exported_changed(self1); + return self1->internal.path; } /** @@ -113,182 +116,217 @@ nm_dbus_object_export (NMDBusObject *self) * auto-exported on future connections). */ void -nm_dbus_object_unexport (NMDBusObject *self) +nm_dbus_object_unexport(gpointer /* (NMDBusObject *) */ self) { - g_return_if_fail (NM_IS_DBUS_OBJECT (self)); + NMDBusObject *self1 = self; - g_return_if_fail (self->internal.path); + g_return_if_fail(NM_IS_DBUS_OBJECT(self1)); - _LOGT ("unexport: \"%s\"", self->internal.path); + g_return_if_fail(self1->internal.path); - /* note that we emit the signal *before* actually unexporting the object. - * The reason is, that listeners want to use this signal to know that - * the object goes away, and clear their D-Bus path to this object. - * - * But this must happen before we actually unregister the object, so - * that we first emit a D-Bus signal that other objects no longer - * reference this object, before finally unregistering the object itself. - * - * The inconvenient part is, that at this point nm_dbus_object_get_path() - * still returns the path. So, the callee needs to handle that. Possibly - * by using "nm_dbus_object_get_path_still_exported()". */ - self->internal.is_unexporting = TRUE; + _LOGT("unexport: \"%s\"", self1->internal.path); - _emit_exported_changed (self); + /* note that we emit the signal *before* actually unexporting the object. + * The reason is, that listeners want to use this signal to know that + * the object goes away, and clear their D-Bus path to this object. + * + * But this must happen before we actually unregister the object, so + * that we first emit a D-Bus signal that other objects no longer + * reference this object, before finally unregistering the object itself. + * + * The inconvenient part is, that at this point nm_dbus_object_get_path() + * still returns the path. So, the callee needs to handle that. Possibly + * by using "nm_dbus_object_get_path_still_exported()". */ + self1->internal.is_unexporting = TRUE; - _nm_dbus_manager_obj_unexport (self); + _emit_exported_changed(self1); - nm_clear_g_free (&self->internal.path); - self->internal.export_version_id = 0; + _nm_dbus_manager_obj_unexport(self1); - self->internal.is_unexporting = FALSE; + nm_clear_g_free(&self1->internal.path); + self1->internal.export_version_id = 0; + + self1->internal.is_unexporting = FALSE; +} + +static gboolean +_unexport_on_idle_cb(gpointer user_data) +{ + gs_unref_object NMDBusObject *self = user_data; + + nm_dbus_object_unexport(self); + return G_SOURCE_REMOVE; +} + +void +nm_dbus_object_unexport_on_idle(gpointer /* (NMDBusObject *) */ self_take) +{ + NMDBusObject *self = g_steal_pointer(&self_take); + + if (!self) + return; + + g_return_if_fail(NM_IS_DBUS_OBJECT(self)); + + g_return_if_fail(self->internal.path); + + /* There is no mechanism to cancel or abort the unexport. It will always + * gonna happen. + * + * However, we register it to block shutdown, so that we ensure that it will happen. */ + + nm_shutdown_wait_obj_register_object(self, "unexport-dbus-obj-on-idle"); + + /* pass on ownership. */ + g_idle_add(_unexport_on_idle_cb, g_steal_pointer(&self)); } /*****************************************************************************/ void -_nm_dbus_object_clear_and_unexport (NMDBusObject **location) +_nm_dbus_object_clear_and_unexport(NMDBusObject **location) { - NMDBusObject *self; + NMDBusObject *self; - g_return_if_fail (location); - if (!*location) - return; + g_return_if_fail(location); + if (!*location) + return; - self = g_steal_pointer (location); + self = g_steal_pointer(location); - g_return_if_fail (NM_IS_DBUS_OBJECT (self)); + g_return_if_fail(NM_IS_DBUS_OBJECT(self)); - if (self->internal.path) - nm_dbus_object_unexport (self); + if (self->internal.path) + nm_dbus_object_unexport(self); - g_object_unref (self); + g_object_unref(self); } /*****************************************************************************/ void -nm_dbus_object_emit_signal_variant (NMDBusObject *self, - const NMDBusInterfaceInfoExtended *interface_info, - const GDBusSignalInfo *signal_info, - GVariant *args) +nm_dbus_object_emit_signal_variant(NMDBusObject * self, + const NMDBusInterfaceInfoExtended *interface_info, + const GDBusSignalInfo * signal_info, + GVariant * args) { - if (!self->internal.path) { - nm_g_variant_unref_floating (args); - return; - } - _nm_dbus_manager_obj_emit_signal (self, interface_info, signal_info, args); + if (!self->internal.path) { + nm_g_variant_unref_floating(args); + return; + } + _nm_dbus_manager_obj_emit_signal(self, interface_info, signal_info, args); } void -nm_dbus_object_emit_signal (NMDBusObject *self, - const NMDBusInterfaceInfoExtended *interface_info, - const GDBusSignalInfo *signal_info, - const char *format, - ...) +nm_dbus_object_emit_signal(NMDBusObject * self, + const NMDBusInterfaceInfoExtended *interface_info, + const GDBusSignalInfo * signal_info, + const char * format, + ...) { - va_list ap; + va_list ap; - nm_assert (NM_IS_DBUS_OBJECT (self)); - nm_assert (format); + nm_assert(NM_IS_DBUS_OBJECT(self)); + nm_assert(format); - if (!self->internal.path) - return; + if (!self->internal.path) + return; - va_start (ap, format); - _nm_dbus_manager_obj_emit_signal (self, - interface_info, - signal_info, - g_variant_new_va (format, NULL, &ap)); - va_end (ap); + va_start(ap, format); + _nm_dbus_manager_obj_emit_signal(self, + interface_info, + signal_info, + g_variant_new_va(format, NULL, &ap)); + va_end(ap); } /*****************************************************************************/ static void -dispatch_properties_changed (GObject *object, - guint n_pspecs, - GParamSpec **pspecs) +dispatch_properties_changed(GObject *object, guint n_pspecs, GParamSpec **pspecs) { - NMDBusObject *self = NM_DBUS_OBJECT (object); + NMDBusObject *self = NM_DBUS_OBJECT(object); - if (self->internal.path) - _nm_dbus_manager_obj_notify (self, n_pspecs, (const GParamSpec *const*) pspecs); + if (self->internal.path) + _nm_dbus_manager_obj_notify(self, n_pspecs, (const GParamSpec *const *) pspecs); - G_OBJECT_CLASS (nm_dbus_object_parent_class)->dispatch_properties_changed (object, n_pspecs, pspecs); + G_OBJECT_CLASS(nm_dbus_object_parent_class) + ->dispatch_properties_changed(object, n_pspecs, pspecs); } /*****************************************************************************/ static void -nm_dbus_object_init (NMDBusObject *self) +nm_dbus_object_init(NMDBusObject *self) { - c_list_init (&self->internal.objects_lst); - c_list_init (&self->internal.registration_lst_head); - self->internal.bus_manager = nm_g_object_ref (nm_dbus_manager_get ()); + c_list_init(&self->internal.objects_lst); + c_list_init(&self->internal.registration_lst_head); + self->internal.bus_manager = nm_g_object_ref(nm_dbus_manager_get()); } static void -constructed (GObject *object) +constructed(GObject *object) { - NMDBusObjectClass *klass; - - G_OBJECT_CLASS (nm_dbus_object_parent_class)->constructed (object); - - klass = NM_DBUS_OBJECT_GET_CLASS (object); - - if (klass->export_on_construction) - nm_dbus_object_export ((NMDBusObject *) object); - - /* NMDBusObject types should be very careful when overwriting notify(). - * It is possible to do, but this is a reminder that it's probably not - * a good idea. - * - * It's not a good idea, because NMDBusObject uses dispatch_properties_changed() - * to emit signals about a bunch of property changes. So, we want to make - * use of g_object_freeze_notify() / g_object_thaw_notify() to combine multiple - * property changes in one signal on D-Bus. Note that notify() is not invoked - * while the signal is frozen, that means, whatever you do inside notify() - * will not make it into the same batch of PropertiesChanged signal. That is - * confusing, and probably not what you want. - * - * Simple solution: don't overwrite notify(). */ - nm_assert (!G_OBJECT_CLASS (klass)->notify); + NMDBusObjectClass *klass; + + G_OBJECT_CLASS(nm_dbus_object_parent_class)->constructed(object); + + klass = NM_DBUS_OBJECT_GET_CLASS(object); + + if (klass->export_on_construction) + nm_dbus_object_export((NMDBusObject *) object); + + /* NMDBusObject types should be very careful when overwriting notify(). + * It is possible to do, but this is a reminder that it's probably not + * a good idea. + * + * It's not a good idea, because NMDBusObject uses dispatch_properties_changed() + * to emit signals about a bunch of property changes. So, we want to make + * use of g_object_freeze_notify() / g_object_thaw_notify() to combine multiple + * property changes in one signal on D-Bus. Note that notify() is not invoked + * while the signal is frozen, that means, whatever you do inside notify() + * will not make it into the same batch of PropertiesChanged signal. That is + * confusing, and probably not what you want. + * + * Simple solution: don't overwrite notify(). */ + nm_assert(!G_OBJECT_CLASS(klass)->notify); } static void -dispose (GObject *object) +dispose(GObject *object) { - NMDBusObject *self = NM_DBUS_OBJECT (object); + NMDBusObject *self = NM_DBUS_OBJECT(object); - /* Objects should have already been unexported by their owner, unless - * we are quitting, where many objects stick around until exit. - */ - if (self->internal.path) { - if (!nm_dbus_manager_is_stopping (nm_dbus_object_get_manager (self))) - g_warn_if_reached (); - nm_dbus_object_unexport (self); - } + /* Objects should have already been unexported by their owner, unless + * we are quitting, where many objects stick around until exit. + */ + if (self->internal.path) { + if (!nm_dbus_manager_is_stopping(nm_dbus_object_get_manager(self))) + g_warn_if_reached(); + nm_dbus_object_unexport(self); + } - G_OBJECT_CLASS (nm_dbus_object_parent_class)->dispose (object); + G_OBJECT_CLASS(nm_dbus_object_parent_class)->dispose(object); - g_clear_object (&self->internal.bus_manager); + g_clear_object(&self->internal.bus_manager); } static void -nm_dbus_object_class_init (NMDBusObjectClass *klass) +nm_dbus_object_class_init(NMDBusObjectClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->constructed = constructed; - object_class->dispose = dispose; - object_class->dispatch_properties_changed = dispatch_properties_changed; - - signals[EXPORTED_CHANGED] = - g_signal_new (NM_DBUS_OBJECT_EXPORTED_CHANGED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + object_class->constructed = constructed; + object_class->dispose = dispose; + object_class->dispatch_properties_changed = dispatch_properties_changed; + + signals[EXPORTED_CHANGED] = g_signal_new(NM_DBUS_OBJECT_EXPORTED_CHANGED, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); } |