summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2020-10-19 22:30:37 +0200
committerAleksander Morgado <aleksander@aleksander.es>2020-10-19 21:14:23 +0000
commit8a54baa346c7fe375b2683e2e333104acf648eff (patch)
tree87246565a37588aa68622d4dbb565934df74099c
parent61739ab934e46c9693e964a20aced349e0f02d51 (diff)
broadband-modem-qmi: fix crash when device removed during init
If the modem goes away (ports removed) during the initialization phase (e.g. while QMI clients are being allocated), the MMPortQmi object will be closed and it will lose its internal QmiDevice. We should therefore consider the lack of QmiDevice a valid usecase in track_qmi_device_removed() and return a GError when that happens. #0 0x00007fb544618cc9 in raise () from /lib/libc.so.6 #1 0x00007fb54461bd68 in abort () from /lib/libc.so.6 #2 0x00007fb544e2213d in g_assertion_message () from /usr/lib/libglib-2.0.so.0 #3 0x00007fb544e221ba in g_assertion_message_expr () from /usr/lib/libglib-2.0.so.0 #4 0x00000000004be584 in track_qmi_device_removed () #5 0x00000000004be5e3 in allocate_next_client () #6 0x00000000004be7b1 in qmi_port_allocate_client_ready () #7 0x00007fb5453690a3 in g_task_return_now () from /usr/lib/libgio-2.0.so.0 #8 0x00007fb54536967e in g_task_return () from /usr/lib/libgio-2.0.so.0 #9 0x00000000004dd8f8 in allocate_client_ready () #10 0x00007fb5453690a3 in g_task_return_now () from /usr/lib/libgio-2.0.so.0 #11 0x00007fb54536967e in g_task_return () from /usr/lib/libgio-2.0.so.0 #12 0x00007fb54591d4de in allocate_cid_ready () from /usr/lib/libqmi-glib.so.5 ...
-rw-r--r--src/mm-broadband-modem-qmi.c34
1 files changed, 26 insertions, 8 deletions
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c
index 8a11318f..6b190f66 100644
--- a/src/mm-broadband-modem-qmi.c
+++ b/src/mm-broadband-modem-qmi.c
@@ -9068,20 +9068,26 @@ qmi_device_removed_cb (QmiDevice *device,
mm_base_modem_set_valid (MM_BASE_MODEM (self), FALSE);
}
-static void
-track_qmi_device_removed (MMBroadbandModemQmi *self,
- MMPortQmi *qmi)
+static gboolean
+track_qmi_device_removed (MMBroadbandModemQmi *self,
+ MMPortQmi *qmi,
+ GError **error)
{
QmiDevice *device;
device = mm_port_qmi_peek_device (qmi);
- g_assert (device);
+ if (!device) {
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+ "Cannot track QMI device removal: QMI port no longer available");
+ return FALSE;
+ }
self->priv->qmi_device_removed_id = g_signal_connect (
device,
QMI_DEVICE_SIGNAL_REMOVED,
G_CALLBACK (qmi_device_removed_cb),
self);
+ return TRUE;
}
static void
@@ -9130,14 +9136,20 @@ static void
allocate_next_client (GTask *task)
{
InitializationStartedContext *ctx;
- MMBroadbandModemQmi *self;
+ MMBroadbandModemQmi *self;
self = g_task_get_source_object (task);
ctx = g_task_get_task_data (task);
if (ctx->service_index == G_N_ELEMENTS (qmi_services)) {
+ GError *error = NULL;
+
/* Done we are, track device removal and launch parent's callback */
- track_qmi_device_removed (self, ctx->qmi);
+ if (!track_qmi_device_removed (self, ctx->qmi, &error)) {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
parent_initialization_started (task);
return;
}
@@ -9206,6 +9218,7 @@ initialization_started (MMBroadbandModem *self,
{
InitializationStartedContext *ctx;
GTask *task;
+ GError *error = NULL;
ctx = g_new0 (InitializationStartedContext, 1);
ctx->qmi = mm_base_modem_get_port_qmi (MM_BASE_MODEM (self));
@@ -9218,7 +9231,7 @@ initialization_started (MMBroadbandModem *self,
g_task_return_new_error (task,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
- "Cannot initialize: QMI port went missing");
+ "Cannot initialize: QMI port no longer available");
g_object_unref (task);
return;
}
@@ -9226,7 +9239,12 @@ initialization_started (MMBroadbandModem *self,
if (mm_port_qmi_is_open (ctx->qmi)) {
/* Nothing to be done, just track device removal and launch parent's
* callback */
- track_qmi_device_removed (MM_BROADBAND_MODEM_QMI (self), ctx->qmi);
+ if (!track_qmi_device_removed (MM_BROADBAND_MODEM_QMI (self), ctx->qmi, &error)) {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
parent_initialization_started (task);
return;
}