mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-03 18:40:16 +01:00
manager: make asynchrounous operations cancellable
It is often wrong to take a reference to keep the instance alive during the asynchronous request, because it means the instance cannot be destroyed as long as the (non cancellable) request is bending. Fix that for NMModemManager and pass a cancallable along.
This commit is contained in:
parent
0adc517407
commit
3128a8a4c1
1 changed files with 116 additions and 33 deletions
|
|
@ -53,6 +53,11 @@ enum {
|
|||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
typedef struct {
|
||||
/* used during g_bus_get() and later during mm_manager_new(). */
|
||||
GCancellable *main_cancellable;
|
||||
|
||||
GCancellable *poke_cancellable;
|
||||
|
||||
GDBusConnection *dbus_connection;
|
||||
MMManager *modem_manager;
|
||||
guint mm_launch_id;
|
||||
|
|
@ -62,6 +67,7 @@ typedef struct {
|
|||
|
||||
#if WITH_OFONO
|
||||
GDBusProxy *ofono_proxy;
|
||||
GCancellable *ofono_cancellable;
|
||||
#endif
|
||||
|
||||
GHashTable *modems;
|
||||
|
|
@ -295,15 +301,27 @@ ofono_signal_cb (GDBusProxy *proxy,
|
|||
}
|
||||
|
||||
static void
|
||||
ofono_enumerate_devices_done (GDBusProxy *proxy, GAsyncResult *res, gpointer user_data)
|
||||
ofono_enumerate_devices_done (GObject *proxy,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMModemManager *manager = NM_MODEM_MANAGER (user_data);
|
||||
NMModemManager *self;
|
||||
NMModemManagerPrivate *priv;
|
||||
gs_free_error GError *error = NULL;
|
||||
GVariant *results;
|
||||
GVariantIter *iter;
|
||||
const char *path;
|
||||
|
||||
results = g_dbus_proxy_call_finish (proxy, res, &error);
|
||||
results = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, &error);
|
||||
if ( !results
|
||||
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
|
||||
self = NM_MODEM_MANAGER (user_data);
|
||||
priv = NM_MODEM_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
g_clear_object (&priv->ofono_cancellable);
|
||||
|
||||
if (!results) {
|
||||
_LOGW ("failed to enumerate oFono devices: %s",
|
||||
error->message);
|
||||
|
|
@ -312,7 +330,7 @@ ofono_enumerate_devices_done (GDBusProxy *proxy, GAsyncResult *res, gpointer use
|
|||
|
||||
g_variant_get (results, "(a(oa{sv}))", &iter);
|
||||
while (g_variant_iter_loop (iter, "(&oa{sv})", &path, NULL))
|
||||
ofono_create_modem (manager, path);
|
||||
ofono_create_modem (self, path);
|
||||
g_variant_iter_free (iter);
|
||||
g_variant_unref (results);
|
||||
}
|
||||
|
|
@ -327,14 +345,17 @@ ofono_check_name_owner (NMModemManager *self)
|
|||
if (name_owner) {
|
||||
_LOGI ("oFono is now available");
|
||||
|
||||
nm_clear_g_cancellable (&priv->ofono_cancellable);
|
||||
priv->ofono_cancellable = g_cancellable_new ();
|
||||
|
||||
g_dbus_proxy_call (priv->ofono_proxy,
|
||||
"GetModems",
|
||||
NULL,
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
NULL,
|
||||
(GAsyncReadyCallback) ofono_enumerate_devices_done,
|
||||
g_object_ref (self));
|
||||
priv->ofono_cancellable,
|
||||
ofono_enumerate_devices_done,
|
||||
self);
|
||||
} else {
|
||||
GHashTableIter iter;
|
||||
NMModem *modem;
|
||||
|
|
@ -361,18 +382,32 @@ ofono_name_owner_changed (GDBusProxy *ofono_proxy,
|
|||
}
|
||||
|
||||
static void
|
||||
ofono_proxy_new_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
|
||||
ofono_proxy_new_cb (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
gs_unref_object NMModemManager *self = NM_MODEM_MANAGER (user_data);
|
||||
NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (self);
|
||||
NMModemManager *self;
|
||||
NMModemManagerPrivate *priv;
|
||||
gs_free_error GError *error = NULL;
|
||||
GDBusProxy *proxy;
|
||||
|
||||
priv->ofono_proxy = g_dbus_proxy_new_finish (res, &error);
|
||||
if (error) {
|
||||
proxy = g_dbus_proxy_new_finish (res, &error);
|
||||
if ( !proxy
|
||||
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
|
||||
self = NM_MODEM_MANAGER (user_data);
|
||||
priv = NM_MODEM_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
g_clear_object (&priv->ofono_cancellable);
|
||||
|
||||
if (!proxy) {
|
||||
_LOGW ("error getting oFono bus proxy: %s", error->message);
|
||||
return;
|
||||
}
|
||||
|
||||
priv->ofono_proxy = proxy;
|
||||
|
||||
g_signal_connect (priv->ofono_proxy,
|
||||
"notify::g-name-owner",
|
||||
G_CALLBACK (ofono_name_owner_changed),
|
||||
|
|
@ -391,16 +426,20 @@ ensure_ofono_client (NMModemManager *self)
|
|||
{
|
||||
NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
g_assert (priv->dbus_connection);
|
||||
nm_assert (priv->dbus_connection);
|
||||
nm_assert (!priv->ofono_cancellable);
|
||||
|
||||
priv->ofono_cancellable = g_cancellable_new ();
|
||||
|
||||
g_dbus_proxy_new (priv->dbus_connection,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
|
||||
NULL,
|
||||
OFONO_DBUS_SERVICE,
|
||||
OFONO_DBUS_PATH,
|
||||
OFONO_DBUS_INTERFACE,
|
||||
NULL,
|
||||
(GAsyncReadyCallback) ofono_proxy_new_cb,
|
||||
g_object_ref (self));
|
||||
priv->ofono_cancellable,
|
||||
ofono_proxy_new_cb,
|
||||
self);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -409,11 +448,22 @@ modem_manager_poke_cb (GObject *connection,
|
|||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMModemManager *self;
|
||||
NMModemManagerPrivate *priv;
|
||||
gs_free_error GError *error = NULL;
|
||||
gs_unref_variant GVariant *result = NULL;
|
||||
gs_unref_object NMModemManager *self = user_data;
|
||||
|
||||
result = g_dbus_connection_call_finish (G_DBUS_CONNECTION (connection), res, &error);
|
||||
|
||||
if ( !result
|
||||
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
|
||||
self = user_data;
|
||||
priv = NM_MODEM_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
g_clear_object (&priv->poke_cancellable);
|
||||
|
||||
if (error) {
|
||||
_LOGW ("error poking ModemManager: %s", error->message);
|
||||
|
||||
|
|
@ -432,6 +482,9 @@ modem_manager_poke (NMModemManager *self)
|
|||
{
|
||||
NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
nm_clear_g_cancellable (&priv->poke_cancellable);
|
||||
priv->poke_cancellable = g_cancellable_new ();
|
||||
|
||||
/* If there is no current owner right away, ensure we poke to get one */
|
||||
g_dbus_connection_call (priv->dbus_connection,
|
||||
"org.freedesktop.ModemManager1",
|
||||
|
|
@ -442,9 +495,9 @@ modem_manager_poke (NMModemManager *self)
|
|||
NULL, /* outputs */
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
NULL, /* cancellable */
|
||||
priv->poke_cancellable,
|
||||
modem_manager_poke_cb, /* callback */
|
||||
g_object_ref (self)); /* user_data */
|
||||
self); /* user_data */
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -470,14 +523,24 @@ manager_new_ready (GObject *source,
|
|||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
gs_unref_object NMModemManager *self = user_data;
|
||||
NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (self);
|
||||
NMModemManager *self;
|
||||
NMModemManagerPrivate *priv;
|
||||
gs_free_error GError *error = NULL;
|
||||
MMManager *modem_manager;
|
||||
|
||||
g_return_if_fail (!priv->modem_manager);
|
||||
modem_manager = mm_manager_new_finish (res, &error);
|
||||
if ( !modem_manager
|
||||
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
|
||||
priv->modem_manager = mm_manager_new_finish (res, &error);
|
||||
if (!priv->modem_manager) {
|
||||
self = user_data;
|
||||
priv = NM_MODEM_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
nm_assert (!priv->modem_manager);
|
||||
|
||||
g_clear_object (&priv->main_cancellable);
|
||||
|
||||
if (!modem_manager) {
|
||||
/* We're not really supposed to get any error here. If we do get one,
|
||||
* though, just re-schedule the MMManager creation after some time.
|
||||
* During this period, name-owner changes won't be followed. */
|
||||
|
|
@ -487,6 +550,8 @@ manager_new_ready (GObject *source,
|
|||
return;
|
||||
}
|
||||
|
||||
priv->modem_manager = modem_manager;
|
||||
|
||||
/* Setup signals in the GDBusObjectManagerClient */
|
||||
priv->mm_name_owner_changed_id =
|
||||
g_signal_connect (priv->modem_manager,
|
||||
|
|
@ -518,11 +583,13 @@ ensure_modem_manager (NMModemManager *self)
|
|||
* we don't really want the MMManager creation to fail. We can always poke
|
||||
* later on if we want to request the autostart */
|
||||
if (!priv->modem_manager) {
|
||||
if (!priv->main_cancellable)
|
||||
priv->main_cancellable = g_cancellable_new ();
|
||||
mm_manager_new (priv->dbus_connection,
|
||||
G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START,
|
||||
NULL,
|
||||
priv->main_cancellable,
|
||||
manager_new_ready,
|
||||
g_object_ref (self));
|
||||
self);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -559,16 +626,26 @@ bus_get_ready (GObject *source,
|
|||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
gs_unref_object NMModemManager *self = NM_MODEM_MANAGER (user_data);
|
||||
NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (self);
|
||||
NMModemManager *self;
|
||||
NMModemManagerPrivate *priv;
|
||||
gs_free_error GError *error = NULL;
|
||||
GDBusConnection *connection;
|
||||
|
||||
priv->dbus_connection = g_bus_get_finish (res, &error);
|
||||
if (!priv->dbus_connection) {
|
||||
connection = g_bus_get_finish (res, &error);
|
||||
if ( !connection
|
||||
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
|
||||
self = NM_MODEM_MANAGER (user_data);
|
||||
priv = NM_MODEM_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
if (!connection) {
|
||||
_LOGW ("error getting bus connection: %s", error->message);
|
||||
return;
|
||||
}
|
||||
|
||||
priv->dbus_connection = connection;
|
||||
|
||||
/* Got the bus, ensure clients */
|
||||
ensure_modem_manager (self);
|
||||
#if WITH_OFONO
|
||||
|
|
@ -585,10 +662,12 @@ nm_modem_manager_init (NMModemManager *self)
|
|||
|
||||
priv->modems = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
|
||||
|
||||
priv->main_cancellable = g_cancellable_new ();
|
||||
|
||||
g_bus_get (G_BUS_TYPE_SYSTEM,
|
||||
NULL,
|
||||
(GAsyncReadyCallback)bus_get_ready,
|
||||
g_object_ref (self));
|
||||
priv->main_cancellable,
|
||||
bus_get_ready,
|
||||
self);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -597,6 +676,9 @@ dispose (GObject *object)
|
|||
NMModemManager *self = NM_MODEM_MANAGER (object);
|
||||
NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
nm_clear_g_cancellable (&priv->main_cancellable);
|
||||
nm_clear_g_cancellable (&priv->poke_cancellable);
|
||||
|
||||
nm_clear_g_source (&priv->mm_launch_id);
|
||||
|
||||
clear_modem_manager (self);
|
||||
|
|
@ -607,6 +689,7 @@ dispose (GObject *object)
|
|||
g_signal_handlers_disconnect_by_func (priv->ofono_proxy, ofono_signal_cb, self);
|
||||
g_clear_object (&priv->ofono_proxy);
|
||||
}
|
||||
nm_clear_g_cancellable (&priv->ofono_cancellable);
|
||||
#endif
|
||||
|
||||
g_clear_object (&priv->dbus_connection);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue