diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2019-12-21 09:45:08 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2019-12-21 15:14:58 +0100 |
commit | 160821383eedccf7e7e2ae1a3cfeb028df7b15ae (patch) | |
tree | 1bad7096f93a2826436ed8a1fff74be97d0f7ff7 | |
parent | 7d3adeca4d9feee55e74831a086e88ae49886efd (diff) |
iface-modem-simple: clear ongoing connect cancellable on early errors
If the Simple.Connect() operation fails before the bearer connection
process starts (e.g. during the previous SIM-PIN checks or explicit
registration attempt), the ongoing connect cancellable is not being
properly cleared, and this would prevent additional new connection
attempts unless an explicit Simple.Disconnect() is called.
$ sudo mmcli -m 1 --simple-connect="operator-id=21403,apn=internet"
error: couldn't connect the modem: 'GDBus.Error:org.freedesktop.ModemManager1.Error.MobileEquipment.NetworkTimeout: Network timeout'
$ sudo mmcli -m 1 --simple-connect="operator-id=21403,apn=internet"
error: couldn't connect the modem: 'GDBus.Error:org.freedesktop.ModemManager1.Error.Core.InProgress: Connection request forbidden: operation already in progress'
$ sudo mmcli -m 1 --simple-connect="operator-id=21403,apn=internet"
error: couldn't connect the modem: 'GDBus.Error:org.freedesktop.ModemManager1.Error.Core.InProgress: Connection request forbidden: operation already in progress'
Fix this, by making sure the ongoing connect cancellable is always
cleared when completing the DBus method invocation that created it.
Fixes https://gitlab.freedesktop.org/mobile-broadband/ModemManager/issues/169
(cherry picked from commit 7a398214f9a4d85399d082634d08b2f47a8b7778)
-rw-r--r-- | src/mm-iface-modem-simple.c | 31 |
1 files changed, 20 insertions, 11 deletions
diff --git a/src/mm-iface-modem-simple.c b/src/mm-iface-modem-simple.c index 1e29c3ce..50c31a00 100644 --- a/src/mm-iface-modem-simple.c +++ b/src/mm-iface-modem-simple.c @@ -238,9 +238,28 @@ typedef struct { } ConnectionContext; static void -connection_context_free (ConnectionContext *ctx) +cleanup_cancellation (ConnectionContext *ctx) { + Private *priv; + + /* The ongoing connect cancellable and the one in the connection context + * must be the same, as they're set together, so if the one in the + * context doesn't exist, do nothing. */ + if (!ctx->cancellable) + return; + + /* If the ongoing connect cancellable is cancelled via the Simple.Disconnect + * method, it won't exist in the private struct, so don't assume they + * both exist. */ + priv = get_private (ctx->self); + g_clear_object (&priv->ongoing_connect); g_clear_object (&ctx->cancellable); +} + +static void +connection_context_free (ConnectionContext *ctx) +{ + cleanup_cancellation (ctx); g_clear_object (&ctx->properties); g_clear_object (&ctx->bearer); g_variant_unref (ctx->dictionary); @@ -487,16 +506,6 @@ completed_if_cancelled (ConnectionContext *ctx) return TRUE; } -static void -cleanup_cancellation (ConnectionContext *ctx) -{ - Private *priv; - - priv = get_private (ctx->self); - g_clear_object (&priv->ongoing_connect); - g_clear_object (&ctx->cancellable); -} - static gboolean setup_cancellation (ConnectionContext *ctx, GError **error) |