gprs: _cid_activated is an 'attaching' state

ofono_gprs_status_notify is an asynchronous notification that messes
with the 'attached' state of the GPRS atom.  This method is normally
prevented from running while an attach is in progress because the
attachment machinery wants to finish up and make it's own determination
of attach state.

When automatic context activation is relevant, as for LTE networks,
the ofono_gprs_cid_activated machinery replaces the usual set_attach
machinery for attaching to the network.  The cid_activated variant,
however, does not guard against simulatenous invocations of
ofono_gprs_status_notify.  This causes a race whereby status_notify
sets the state to 'attached' before the context is fully constructed
and set to active.  If the connection manager sees the 'attached'
state before there are any 'active' contexts, it may decide to
activate a context manually which is not the correct behaviour for
this type of network.

This patch makes the *_cid_activated machinery an 'attaching' state,
introducing the same guards that set_attached has to prevent
ofono_gprs_status_notify from running concurrently.
This commit is contained in:
Jonas Bonn 2017-04-14 23:36:37 +02:00 committed by Denis Kenzior
parent ad39b9003b
commit 1fd419e5b4
1 changed files with 17 additions and 1 deletions

View File

@ -982,6 +982,7 @@ static void pri_read_settings_callback(const struct ofono_error *error,
{
struct pri_context *pri_ctx = data;
struct ofono_gprs_context *gc = pri_ctx->context_driver;
struct ofono_gprs *gprs = pri_ctx->gprs;
DBusConnection *conn = ofono_dbus_get_connection();
dbus_bool_t value;
@ -1006,11 +1007,18 @@ static void pri_read_settings_callback(const struct ofono_error *error,
value = pri_ctx->active;
gprs_set_attached_property(pri_ctx->gprs, TRUE);
gprs->flags &= !GPRS_FLAG_ATTACHING;
gprs_set_attached_property(gprs, TRUE);
ofono_dbus_signal_property_changed(conn, pri_ctx->path,
OFONO_CONNECTION_CONTEXT_INTERFACE,
"Active", DBUS_TYPE_BOOLEAN, &value);
if (gprs->flags & GPRS_FLAG_RECHECK) {
gprs->flags &= ~GPRS_FLAG_RECHECK;
gprs_netreg_update(gprs);
}
}
static DBusMessage *pri_set_apn(struct pri_context *ctx, DBusConnection *conn,
@ -2031,6 +2039,14 @@ void ofono_gprs_cid_activated(struct ofono_gprs *gprs, unsigned int cid,
pri_set_apn(pri_ctx, conn, NULL, apn);
}
/* Prevent ofono_gprs_status_notify from changing the 'attached'
* state until after the context has been set to 'active' in
* the pri_read_settings_callback; this prevents a race where
* the connection manager sees the modem as attached before there
* is an active context.
*/
gprs->flags |= GPRS_FLAG_ATTACHING;
gc->driver->read_settings(gc, cid, pri_read_settings_callback, pri_ctx);
}