diff options
author | Aleksander Morgado <aleksander@lanedo.com> | 2012-10-11 09:23:49 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2012-10-11 09:23:49 +0200 |
commit | 014d0688ff2eebd5ef821ef74e20ba704b52634d (patch) | |
tree | 164821926361d2670968c5e4e8e5d8de4eac870c /src | |
parent | ba64c49f3689f6fbc4dd740a39941b691768b04a (diff) |
core,qmi: don't assume QMI port is always available
When the modem gets unplugged all ports disappear from the modem, so don't
assume the port is always given.
E.g. if the unplug happens in the middle of the initialization sequence we may
end up with nasty segfaults:
Crash reason: SIGSEGV
Crash address: 0x0
Thread 0 (crashed)
0 ModemManager!mm_qmi_port_peek_client [mm-qmi-port.c : 50 + 0x0]
rbx = 0x00007fbb5c1d8010 r12 = 0x0000000000000003
r13 = 0x00007fbb5c1f9880 r14 = 0x00007fbb59a30980
r15 = 0x00007fbb5c187a60 rip = 0x00007fbb5a1a54c0
rsp = 0x00007fffc6c0f628 rbp = 0x00007fffc6c0f650
Found by: given as instruction pointer in context
1 ModemManager!peek_qmi_client [mm-broadband-modem-qmi.c : 109 + 0x24]
rbx = 0x00007fbb5c1d8010 r12 = 0x0000000000000003
r13 = 0x00007fbb5c1f9880 r14 = 0x00007fbb59a30980
r15 = 0x00007fbb5c187a60 rip = 0x00007fbb5a193851
rsp = 0x00007fffc6c0f630 rbp = 0x00007fffc6c0f650
Found by: call frame info
2 ModemManager!ensure_qmi_client [mm-broadband-modem-qmi.c : 132 + 0x4]
rbx = 0x00007fbb5c1d8010 r12 = 0x00007fbb5a165140
r13 = 0x00007fbb5c1f9880 r14 = 0x00007fbb59a30980
r15 = 0x00007fbb5c187a60 rip = 0x00007fbb5a1938e4
rsp = 0x00007fffc6c0f650 rbp = 0x00007fffc6c0f690
Found by: call frame info
...
Reported by: Ben Chan <benchan@chromium.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-broadband-modem-qmi.c | 45 | ||||
-rw-r--r-- | src/mm-sim-qmi.c | 26 | ||||
-rw-r--r-- | src/mm-sms-qmi.c | 26 |
3 files changed, 76 insertions, 21 deletions
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c index d781301f..7a6f13ed 100644 --- a/src/mm-broadband-modem-qmi.c +++ b/src/mm-broadband-modem-qmi.c @@ -104,9 +104,19 @@ peek_qmi_client (MMBroadbandModemQmi *self, QmiService service, GError **error) { + MMQmiPort *port; QmiClient *client; - client = mm_qmi_port_peek_client (mm_base_modem_peek_port_qmi (MM_BASE_MODEM (self)), + port = mm_base_modem_peek_port_qmi (MM_BASE_MODEM (self)); + if (!port) { + g_set_error (error, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Couldn't peek QMI port"); + return NULL; + } + + client = mm_qmi_port_peek_client (port, service, MM_QMI_PORT_FLAG_DEFAULT); if (!client) @@ -4941,16 +4951,21 @@ messaging_check_support (MMIfaceModemMessaging *self, { GSimpleAsyncResult *result; gboolean supported; + MMQmiPort *port; result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, messaging_check_support); - /* If we have support for the WMS client, messaging is supported */ - supported = !!mm_qmi_port_peek_client (mm_base_modem_peek_port_qmi (MM_BASE_MODEM (self)), - QMI_SERVICE_WMS, - MM_QMI_PORT_FLAG_DEFAULT); + port = mm_base_modem_peek_port_qmi (MM_BASE_MODEM (self)); + if (!port) + supported = FALSE; + else + /* If we have support for the WMS client, messaging is supported */ + supported = !!mm_qmi_port_peek_client (port, + QMI_SERVICE_WMS, + MM_QMI_PORT_FLAG_DEFAULT); /* We only handle 3GPP messaging (PDU based) currently, so just ignore * CDMA-only QMI modems */ @@ -5673,6 +5688,7 @@ parent_load_capabilities_ready (MMIfaceModemLocation *self, { MMModemLocationSource sources; GError *error = NULL; + MMQmiPort *port; sources = iface_modem_location_parent->load_capabilities_finish (self, res, &error); if (error) { @@ -5682,11 +5698,13 @@ parent_load_capabilities_ready (MMIfaceModemLocation *self, return; } + port = mm_base_modem_peek_port_qmi (MM_BASE_MODEM (self)); + /* Now our own check. * If we have support for the PDS client, GPS location is supported */ - if (mm_qmi_port_peek_client (mm_base_modem_peek_port_qmi (MM_BASE_MODEM (self)), - QMI_SERVICE_PDS, - MM_QMI_PORT_FLAG_DEFAULT)) + if (port && mm_qmi_port_peek_client (port, + QMI_SERVICE_PDS, + MM_QMI_PORT_FLAG_DEFAULT)) sources |= (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | MM_MODEM_LOCATION_SOURCE_GPS_RAW); /* So we're done, complete */ @@ -6931,7 +6949,16 @@ initialization_started (MMBroadbandModem *self, user_data, initialization_started); ctx->qmi = mm_base_modem_get_port_qmi (MM_BASE_MODEM (self)); - g_assert (ctx->qmi); + + /* This may happen if we unplug the modem unexpectedly */ + if (!ctx->qmi) { + g_simple_async_result_set_error (ctx->result, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Cannot initialize: QMI port went missing"); + initialization_started_context_complete_and_free (ctx); + return; + } if (mm_qmi_port_is_open (ctx->qmi)) { /* Nothing to be done, just launch parent's callback */ diff --git a/src/mm-sim-qmi.c b/src/mm-sim-qmi.c index 63111b54..578bf774 100644 --- a/src/mm-sim-qmi.c +++ b/src/mm-sim-qmi.c @@ -40,16 +40,30 @@ ensure_qmi_client (MMSimQmi *self, { MMBaseModem *modem = NULL; QmiClient *client; + MMQmiPort *port; g_object_get (self, MM_SIM_MODEM, &modem, NULL); g_assert (MM_IS_BASE_MODEM (modem)); - client = mm_qmi_port_peek_client (mm_base_modem_peek_port_qmi (modem), + port = mm_base_modem_peek_port_qmi (modem); + g_object_unref (modem); + + if (!port) { + g_simple_async_report_error_in_idle (G_OBJECT (self), + callback, + user_data, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Couldn't peek QMI port"); + return FALSE; + } + + client = mm_qmi_port_peek_client (port, service, MM_QMI_PORT_FLAG_DEFAULT); - if (!client) + if (!client) { g_simple_async_report_error_in_idle (G_OBJECT (self), callback, user_data, @@ -57,11 +71,11 @@ ensure_qmi_client (MMSimQmi *self, MM_CORE_ERROR_FAILED, "Couldn't peek client for service '%s'", qmi_service_get_string (service)); - else - *o_client = client; + return FALSE; + } - g_object_unref (modem); - return !!client; + *o_client = client; + return TRUE; } /*****************************************************************************/ diff --git a/src/mm-sms-qmi.c b/src/mm-sms-qmi.c index 2b167ed2..fbdaeb02 100644 --- a/src/mm-sms-qmi.c +++ b/src/mm-sms-qmi.c @@ -43,16 +43,30 @@ ensure_qmi_client (MMSmsQmi *self, { MMBaseModem *modem = NULL; QmiClient *client; + MMQmiPort *port; g_object_get (self, MM_SMS_MODEM, &modem, NULL); g_assert (MM_IS_BASE_MODEM (modem)); - client = mm_qmi_port_peek_client (mm_base_modem_peek_port_qmi (modem), + port = mm_base_modem_peek_port_qmi (modem); + g_object_unref (modem); + + if (!port) { + g_simple_async_report_error_in_idle (G_OBJECT (self), + callback, + user_data, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Couldn't peek QMI port"); + return FALSE; + } + + client = mm_qmi_port_peek_client (port, service, MM_QMI_PORT_FLAG_DEFAULT); - if (!client) + if (!client) { g_simple_async_report_error_in_idle (G_OBJECT (self), callback, user_data, @@ -60,11 +74,11 @@ ensure_qmi_client (MMSmsQmi *self, MM_CORE_ERROR_FAILED, "Couldn't peek client for service '%s'", qmi_service_get_string (service)); - else - *o_client = client; + return FALSE; + } - g_object_unref (modem); - return !!client; + *o_client = client; + return TRUE; } /*****************************************************************************/ |