diff options
author | Aleksander Morgado <aleksander@lanedo.com> | 2011-05-16 12:16:04 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2011-06-05 17:51:00 +0200 |
commit | 9323daec015ecad65c39b6020b62e864c027d858 (patch) | |
tree | 3a26a62be12c53effbdefabdc70ae27eea728e0e /src | |
parent | f7dff81eecd6694c2596200fc2c3226de0396b7d (diff) |
core, plugins: if modem removed don't process response
We try to avoid a memory leak when info->error is reset, as well as a second
re-schedule of the info.
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-callback-info.c | 8 | ||||
-rw-r--r-- | src/mm-callback-info.h | 2 | ||||
-rw-r--r-- | src/mm-generic-cdma.c | 117 | ||||
-rw-r--r-- | src/mm-generic-gsm.c | 490 | ||||
-rw-r--r-- | src/mm-modem-base.c | 20 | ||||
-rw-r--r-- | src/mm-modem.c | 19 | ||||
-rw-r--r-- | src/mm-modem.h | 2 |
7 files changed, 448 insertions, 210 deletions
diff --git a/src/mm-callback-info.c b/src/mm-callback-info.c index 1986bb55..aa1f13ab 100644 --- a/src/mm-callback-info.c +++ b/src/mm-callback-info.c @@ -182,6 +182,14 @@ mm_callback_info_get_data (MMCallbackInfo *info, const char *key) return quark ? g_datalist_id_get_data (&info->qdata, quark) : NULL; } +gboolean +mm_callback_info_check_modem_removed (MMCallbackInfo *info) +{ + g_return_val_if_fail (info != NULL, TRUE); + + return (info->modem ? FALSE : TRUE); +} + MMCallbackInfo * mm_callback_info_ref (MMCallbackInfo *info) { diff --git a/src/mm-callback-info.h b/src/mm-callback-info.h index ef4d65fc..42d9908e 100644 --- a/src/mm-callback-info.h +++ b/src/mm-callback-info.h @@ -70,6 +70,8 @@ void mm_callback_info_set_data (MMCallbackInfo *info, gpointer mm_callback_info_get_data (MMCallbackInfo *info, const char *key); +gboolean mm_callback_info_check_modem_removed (MMCallbackInfo *info); + MMCallbackInfo *mm_callback_info_ref (MMCallbackInfo *info); void mm_callback_info_unref (MMCallbackInfo *info); diff --git a/src/mm-generic-cdma.c b/src/mm-generic-cdma.c index 0a95e7b1..378555b7 100644 --- a/src/mm-generic-cdma.c +++ b/src/mm-generic-cdma.c @@ -619,6 +619,11 @@ init_done (MMAtSerialPort *port, { MMCallbackInfo *info = (MMCallbackInfo *) user_data; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + if (error) { mm_modem_set_state (MM_MODEM (info->modem), MM_MODEM_STATE_DISABLED, @@ -699,10 +704,14 @@ disable_all_done (MMModem *modem, GError *error, gpointer user_data) { MMCallbackInfo *info = user_data; - info->error = mm_modem_check_removed (modem, error); - if (info->error) { - if (modem) - disable_set_previous_state (modem, info); + /* If the modem has already been removed, return without + * scheduling callback */ + if (!modem || mm_callback_info_check_modem_removed (info)) + return; + + if (error) { + info->error = g_error_copy (error); + disable_set_previous_state (modem, info); } else { MMGenericCdma *self = MM_GENERIC_CDMA (info->modem); MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (self); @@ -725,10 +734,15 @@ disable_flash_done (MMSerialPort *port, MMCallbackInfo *info = user_data; MMGenericCdma *self; - info->error = mm_modem_check_removed (info->modem, error); - if (info->error) { - if (info->modem) - disable_set_previous_state (info->modem, info); + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + + if (error) { + info->error = g_error_copy (error); + + disable_set_previous_state (info->modem, info); mm_callback_info_schedule (info); return; } @@ -787,10 +801,14 @@ dial_done (MMAtSerialPort *port, { MMCallbackInfo *info = (MMCallbackInfo *) user_data; - info->error = mm_modem_check_removed (info->modem, error); - if (info->error) { - if (info->modem) - update_enabled_state (MM_GENERIC_CDMA (info->modem), FALSE, MM_MODEM_STATE_REASON_NONE); + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + + if (error) { + info->error = g_error_copy (error); + update_enabled_state (MM_GENERIC_CDMA (info->modem), FALSE, MM_MODEM_STATE_REASON_NONE); } else { MMGenericCdma *self = MM_GENERIC_CDMA (info->modem); MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (self); @@ -831,15 +849,19 @@ disconnect_flash_done (MMSerialPort *port, MMCallbackInfo *info = (MMCallbackInfo *) user_data; MMModemState prev_state; - info->error = mm_modem_check_removed (info->modem, error); - if (info->error) { - if (info->modem) { - /* Reset old state since the operation failed */ - prev_state = GPOINTER_TO_UINT (mm_callback_info_get_data (info, MM_GENERIC_CDMA_PREV_STATE_TAG)); - mm_modem_set_state (MM_MODEM (info->modem), - prev_state, - MM_MODEM_STATE_REASON_NONE); - } + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + + if (error) { + info->error = g_error_copy (error); + + /* Reset old state since the operation failed */ + prev_state = GPOINTER_TO_UINT (mm_callback_info_get_data (info, MM_GENERIC_CDMA_PREV_STATE_TAG)); + mm_modem_set_state (MM_MODEM (info->modem), + prev_state, + MM_MODEM_STATE_REASON_NONE); } else { mm_port_set_connected (MM_GENERIC_CDMA_GET_PRIVATE (info->modem)->data, FALSE); update_enabled_state (MM_GENERIC_CDMA (info->modem), FALSE, MM_MODEM_STATE_REASON_NONE); @@ -929,6 +951,11 @@ get_signal_quality_done (MMAtSerialPort *port, MMCallbackInfo *info = (MMCallbackInfo *) user_data; char *reply = response->str; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + if (error) { if (mm_callback_info_get_data (info, CSQ2_TRIED)) info->error = g_error_copy (error); @@ -1077,6 +1104,11 @@ get_string_done (MMAtSerialPort *port, MMCallbackInfo *info = (MMCallbackInfo *) user_data; const char *p; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + if (error) info->error = g_error_copy (error); else { @@ -1207,6 +1239,11 @@ serving_system_done (MMAtSerialPort *port, unsigned char band = 'Z'; gboolean success = FALSE; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + if (error) { info->error = g_error_copy (error); goto out; @@ -1500,8 +1537,14 @@ subclass_reg_query_done (MMModemCdma *cdma, { MMCallbackInfo *info = (MMCallbackInfo *) user_data; - info->error = mm_modem_check_removed (info->modem, error); - if (!info->error) { + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + + if (error) + info->error = g_error_copy (error); + else { /* Set final registration state */ set_callback_1x_state_helper (info, cdma_reg_state); set_callback_evdo_state_helper (info, evdo_reg_state); @@ -1520,6 +1563,11 @@ reg_query_speri_done (MMAtSerialPort *port, gboolean roam = FALSE; const char *p; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + if (error) goto done; @@ -1559,6 +1607,11 @@ reg_query_spservice_done (MMAtSerialPort *port, MMModemCdmaRegistrationState cdma_state = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN; MMModemCdmaRegistrationState evdo_state = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + if (error) info->error = g_error_copy (error); else if (mm_cdma_parse_spservice_response (response->str, &cdma_state, &evdo_state)) { @@ -1661,6 +1714,11 @@ get_analog_digital_done (MMAtSerialPort *port, const char *reply; long int int_cad; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + if (error) { info->error = g_error_copy (error); goto error; @@ -1994,7 +2052,7 @@ reg_state_changed (MMModemCdma *self, MMModemCdmaRegistrationState evdo_new_state, gpointer user_data) { -/* Disabled for now... changing the registration state from the +/* Disabled for now... changing the registration state from the * subclass' query_registration_state handler also emits the registration * state changed signal, which will call this function, and execute * simple_state_machine() to advance to the next state. Then however @@ -2030,9 +2088,14 @@ simple_state_machine (MMModem *modem, GError *error, gpointer user_data) const char *str; guint id; - info->error = mm_modem_check_removed (modem, error); - if (info->error) + /* Do nothing if modem removed */ + if (!modem || mm_callback_info_check_modem_removed (info)) + return; + + if (error) { + info->error = g_error_copy (error); goto out; + } switch (state) { case SIMPLE_STATE_BEGIN: @@ -2095,7 +2158,7 @@ simple_connect (MMModemSimple *simple, info = mm_callback_info_new (MM_MODEM (simple), callback, user_data); priv->simple_connect_info = info; - mm_callback_info_set_data (info, "simple-connect-properties", + mm_callback_info_set_data (info, "simple-connect-properties", g_hash_table_ref (properties), (GDestroyNotify) g_hash_table_unref); diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index b67cecff..bcc158e6 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -275,6 +275,11 @@ pin_check_done (MMAtSerialPort *port, MMCallbackInfo *info = (MMCallbackInfo *) user_data; gboolean parsed = FALSE; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + if (error) info->error = g_error_copy (error); else if (response && strstr (response->str, "+CPIN: ")) { @@ -513,6 +518,11 @@ real_get_iccid_done (MMAtSerialPort *port, gboolean success = FALSE; char buf[21], swapped[21]; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + if (error) { info->error = g_error_copy (error); goto done; @@ -1064,21 +1074,21 @@ cgreg1_done (MMAtSerialPort *port, { MMCallbackInfo *info = user_data; - info->error = mm_modem_check_removed (info->modem, error); - if (info->modem) { - if (info->error) { - MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; - g_clear_error (&info->error); + if (error) { + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); - /* The modem doesn't like unsolicited CGREG, so we'll need to poll */ - priv->cgreg_poll = TRUE; - } else - mm_callback_info_set_data (info, CGREG_NUM_TAG, GUINT_TO_POINTER (1), NULL); + /* The modem doesn't like unsolicited CGREG, so we'll need to poll */ + priv->cgreg_poll = TRUE; + } else + mm_callback_info_set_data (info, CGREG_NUM_TAG, GUINT_TO_POINTER (1), NULL); - /* Success; get initial state */ - mm_at_serial_port_queue_command (port, "+CGREG?", 10, reg_poll_response, info->modem); - } + /* Success; get initial state */ + mm_at_serial_port_queue_command (port, "+CGREG?", 10, reg_poll_response, info->modem); initial_unsolicited_reg_check_done (info); } @@ -1091,27 +1101,25 @@ cgreg2_done (MMAtSerialPort *port, { MMCallbackInfo *info = user_data; - /* Ignore errors except modem removal errors */ - info->error = mm_modem_check_removed (info->modem, error); - if (info->modem) { - if (info->error) { - g_clear_error (&info->error); - /* Try CGREG=1 instead */ - mm_at_serial_port_queue_command (port, "+CGREG=1", 3, cgreg1_done, info); - } else { - add_loc_capability (MM_GENERIC_GSM (info->modem), MM_MODEM_LOCATION_CAPABILITY_GSM_LAC_CI); + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; - mm_callback_info_set_data (info, CGREG_NUM_TAG, GUINT_TO_POINTER (2), NULL); + /* Ignore errors */ + if (error) { + /* Try CGREG=1 instead */ + mm_at_serial_port_queue_command (port, "+CGREG=1", 3, cgreg1_done, info); + } else { + add_loc_capability (MM_GENERIC_GSM (info->modem), MM_MODEM_LOCATION_CAPABILITY_GSM_LAC_CI); - /* Success; get initial state */ - mm_at_serial_port_queue_command (port, "+CGREG?", 10, reg_poll_response, info->modem); + mm_callback_info_set_data (info, CGREG_NUM_TAG, GUINT_TO_POINTER (2), NULL); - /* All done */ - initial_unsolicited_reg_check_done (info); - } - } else { - /* Modem got removed */ - mm_callback_info_schedule (info); + /* Success; get initial state */ + mm_at_serial_port_queue_command (port, "+CGREG?", 10, reg_poll_response, info->modem); + + /* All done */ + initial_unsolicited_reg_check_done (info); } } @@ -1122,28 +1130,26 @@ creg1_done (MMAtSerialPort *port, gpointer user_data) { MMCallbackInfo *info = user_data; + MMGenericGsmPrivate *priv; - info->error = mm_modem_check_removed (info->modem, error); - if (info->modem) { - MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; - if (info->error) { - g_clear_error (&info->error); + priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); - /* The modem doesn't like unsolicited CREG, so we'll need to poll */ - priv->creg_poll = TRUE; - } else - mm_callback_info_set_data (info, CREG_NUM_TAG, GUINT_TO_POINTER (1), NULL); + if (error) { + /* The modem doesn't like unsolicited CREG, so we'll need to poll */ + priv->creg_poll = TRUE; + } else + mm_callback_info_set_data (info, CREG_NUM_TAG, GUINT_TO_POINTER (1), NULL); - /* Success; get initial state */ - mm_at_serial_port_queue_command (port, "+CREG?", 10, reg_poll_response, info->modem); + /* Success; get initial state */ + mm_at_serial_port_queue_command (port, "+CREG?", 10, reg_poll_response, info->modem); - /* Now try to set up CGREG messages */ - mm_at_serial_port_queue_command (port, "+CGREG=2", 3, cgreg2_done, info); - } else { - /* Modem got removed */ - mm_callback_info_schedule (info); - } + /* Now try to set up CGREG messages */ + mm_at_serial_port_queue_command (port, "+CGREG=2", 3, cgreg2_done, info); } static void @@ -1154,26 +1160,24 @@ creg2_done (MMAtSerialPort *port, { MMCallbackInfo *info = user_data; - /* Ignore errors except modem removal errors */ - info->error = mm_modem_check_removed (info->modem, error); - if (info->modem) { - if (info->error) { - g_clear_error (&info->error); - mm_at_serial_port_queue_command (port, "+CREG=1", 3, creg1_done, info); - } else { - add_loc_capability (MM_GENERIC_GSM (info->modem), MM_MODEM_LOCATION_CAPABILITY_GSM_LAC_CI); + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; - mm_callback_info_set_data (info, CREG_NUM_TAG, GUINT_TO_POINTER (2), NULL); + /* Ignore errors */ + if (error) + mm_at_serial_port_queue_command (port, "+CREG=1", 3, creg1_done, info); + else { + add_loc_capability (MM_GENERIC_GSM (info->modem), MM_MODEM_LOCATION_CAPABILITY_GSM_LAC_CI); - /* Success; get initial state */ - mm_at_serial_port_queue_command (port, "+CREG?", 10, reg_poll_response, info->modem); + mm_callback_info_set_data (info, CREG_NUM_TAG, GUINT_TO_POINTER (2), NULL); - /* Now try to set up CGREG messages */ - mm_at_serial_port_queue_command (port, "+CGREG=2", 3, cgreg2_done, info); - } - } else { - /* Modem got removed */ - mm_callback_info_schedule (info); + /* Success; get initial state */ + mm_at_serial_port_queue_command (port, "+CREG?", 10, reg_poll_response, info->modem); + + /* Now try to set up CGREG messages */ + mm_at_serial_port_queue_command (port, "+CGREG=2", 3, cgreg2_done, info); } } @@ -1182,20 +1186,23 @@ enable_failed (MMModem *modem, GError *error, MMCallbackInfo *info) { MMGenericGsmPrivate *priv; - info->error = mm_modem_check_removed (modem, error); + /* If modem already removed, do nothing */ + if (!modem || mm_callback_info_check_modem_removed (info)) + return; - if (modem) { - mm_modem_set_state (modem, - MM_MODEM_STATE_DISABLED, - MM_MODEM_STATE_REASON_NONE); + if (error) + info->error = g_error_copy (error); - priv = MM_GENERIC_GSM_GET_PRIVATE (modem); + mm_modem_set_state (modem, + MM_MODEM_STATE_DISABLED, + MM_MODEM_STATE_REASON_NONE); - if (priv->primary && mm_serial_port_is_open (MM_SERIAL_PORT (priv->primary))) - mm_serial_port_close_force (MM_SERIAL_PORT (priv->primary)); - if (priv->secondary && mm_serial_port_is_open (MM_SERIAL_PORT (priv->secondary))) - mm_serial_port_close_force (MM_SERIAL_PORT (priv->secondary)); - } + priv = MM_GENERIC_GSM_GET_PRIVATE (modem); + + if (priv->primary && mm_serial_port_is_open (MM_SERIAL_PORT (priv->primary))) + mm_serial_port_close_force (MM_SERIAL_PORT (priv->primary)); + if (priv->secondary && mm_serial_port_is_open (MM_SERIAL_PORT (priv->secondary))) + mm_serial_port_close_force (MM_SERIAL_PORT (priv->secondary)); mm_callback_info_schedule (info); } @@ -1468,6 +1475,11 @@ enable_done (MMAtSerialPort *port, { MMCallbackInfo *info = (MMCallbackInfo *) user_data; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + /* Let subclasses handle the power up command response/error; many devices * don't support +CFUN, but for those that do let them handle the error * correctly. @@ -1488,6 +1500,11 @@ init_done (MMAtSerialPort *port, MMCallbackInfo *info = (MMCallbackInfo *) user_data; char *cmd = NULL; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + if (error) { mm_generic_gsm_enable_complete (MM_GENERIC_GSM (info->modem), error, info); return; @@ -1590,8 +1607,14 @@ disable_done (MMAtSerialPort *port, { MMCallbackInfo *info = user_data; - info->error = mm_modem_check_removed (info->modem, error); - if (!info->error) { + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + + if (error) + info->error = g_error_copy (error); + else { MMGenericGsm *self = MM_GENERIC_GSM (info->modem); mm_serial_port_close_force (MM_SERIAL_PORT (port)); @@ -1623,15 +1646,19 @@ disable_flash_done (MMSerialPort *port, MMModemState prev_state; char *cmd = NULL; - info->error = mm_modem_check_removed (info->modem, error); - if (info->error) { - if (info->modem) { - /* Reset old state since the operation failed */ - prev_state = GPOINTER_TO_UINT (mm_callback_info_get_data (info, MM_GENERIC_GSM_PREV_STATE_TAG)); - mm_modem_set_state (MM_MODEM (info->modem), - prev_state, - MM_MODEM_STATE_REASON_NONE); - } + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + + if (error) { + info->error = g_error_copy (error); + + /* Reset old state since the operation failed */ + prev_state = GPOINTER_TO_UINT (mm_callback_info_get_data (info, MM_GENERIC_GSM_PREV_STATE_TAG)); + mm_modem_set_state (MM_MODEM (info->modem), + prev_state, + MM_MODEM_STATE_REASON_NONE); mm_callback_info_schedule (info); return; @@ -1739,6 +1766,11 @@ get_string_done (MMAtSerialPort *port, { MMCallbackInfo *info = (MMCallbackInfo *) user_data; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + if (error) info->error = g_error_copy (error); else @@ -1760,6 +1792,11 @@ get_mnc_length_done (MMAtSerialPort *port, char hex[51]; char *bin; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + if (error) { info->error = g_error_copy (error); goto done; @@ -2016,35 +2053,33 @@ static void pin_puk_recheck_done (MMModem *modem, GError *error, gpointer user_data) { MMCallbackInfo *info = (MMCallbackInfo *) user_data; + MMGenericGsmPrivate *priv; MMSerialPort *port; GError *saved_error; + /* Do nothing if modem removed */ + if (!modem || mm_callback_info_check_modem_removed (info)) + return; + + priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); + /* Clear the pin check timeout to ensure that it won't ever get a * stale MMCallbackInfo if the modem got removed. We'll reschedule it here * anyway if needed. */ - if (info->modem) { - MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); - - if (priv->pin_check_timeout) - g_source_remove (priv->pin_check_timeout); - priv->pin_check_timeout = 0; - } + if (priv->pin_check_timeout) + g_source_remove (priv->pin_check_timeout); + priv->pin_check_timeout = 0; - /* modem could have been removed before we get here, in which case - * 'modem' will be NULL. - */ - info->error = mm_modem_check_removed (modem, error); + /* Propagate the error to the info */ + if (error) + info->error = g_error_copy (error); /* If the modem wasn't removed, and the modem isn't ready yet, ask it for * the current PIN status a few times since some devices take a bit to fully * enable themselves after a SIM PIN/PUK unlock. */ - if ( info->modem - && info->error - && !g_error_matches (info->error, MM_MODEM_ERROR, MM_MODEM_ERROR_REMOVED)) { - MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); - + if (info->error && !g_error_matches (info->error, MM_MODEM_ERROR, MM_MODEM_ERROR_REMOVED)) { if (priv->pin_check_tries < 4) { g_clear_error (&info->error); priv->pin_check_tries++; @@ -2055,13 +2090,13 @@ pin_puk_recheck_done (MMModem *modem, GError *error, gpointer user_data) /* Otherwise, clean up and return the PIN check result */ port = mm_callback_info_get_data (info, PIN_PORT_TAG); - if (modem && port) + if (port) mm_serial_port_close (port); /* If we have a saved error from sending PIN/PUK, return that to callers */ saved_error = mm_callback_info_get_data (info, SAVED_ERROR_TAG); if (saved_error) { - if (info->modem && !mm_modem_base_get_unlock_required (MM_MODEM_BASE (info->modem))) { + if (!mm_modem_base_get_unlock_required (MM_MODEM_BASE (info->modem))) { /* Original unlock failed but the modem is actually unlocked, so * return success. Sometimes happens if the modem doesn't allow * CPIN="xxxx" when it's already unlocked and returns an error. @@ -2085,6 +2120,11 @@ send_puk_done (MMAtSerialPort *port, { MMCallbackInfo *info = (MMCallbackInfo *) user_data; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + if (error) { if (error->domain != MM_MOBILE_ERROR) { info->error = g_error_copy (error); @@ -2149,6 +2189,11 @@ send_pin_done (MMAtSerialPort *port, { MMCallbackInfo *info = (MMCallbackInfo *) user_data; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + if (error) { if (error->domain != MM_MOBILE_ERROR) { info->error = g_error_copy (error); @@ -2212,6 +2257,11 @@ enable_pin_done (MMAtSerialPort *port, { MMCallbackInfo *info = (MMCallbackInfo *) user_data; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + if (error) info->error = g_error_copy (error); mm_callback_info_schedule (info); @@ -2242,6 +2292,11 @@ change_pin_done (MMAtSerialPort *port, { MMCallbackInfo *info = (MMCallbackInfo *) user_data; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + if (error) info->error = g_error_copy (error); mm_callback_info_schedule (info); @@ -2734,11 +2789,19 @@ get_reg_status_done (MMAtSerialPort *port, gpointer user_data) { MMCallbackInfo *info = (MMCallbackInfo *) user_data; - MMGenericGsm *self = MM_GENERIC_GSM (info->modem); - MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); + MMGenericGsm *self; + MMGenericGsmPrivate *priv; guint id; MMModemGsmNetworkRegStatus status; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + + self = MM_GENERIC_GSM (info->modem); + priv = MM_GENERIC_GSM_GET_PRIVATE (self); + /* This function should only get called during the connect sequence when * polling for registration state, since explicit registration requests * from D-Bus clients are filled from the cached registration state. @@ -2806,10 +2869,17 @@ register_done (MMAtSerialPort *port, gpointer user_data) { MMCallbackInfo *info = user_data; - MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); + MMGenericGsmPrivate *priv; mm_callback_info_unref (info); + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + + priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); + /* If the registration timed out (and thus pending_reg_info will be NULL) * and the modem eventually got around to sending the response for the * registration request then just ignore the response since the callback is @@ -2986,6 +3056,11 @@ connect_report_done (MMAtSerialPort *port, MMCallbackInfo *info = (MMCallbackInfo *) user_data; GError *real_error; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + /* If the CEER command was successful, copy that error reason into the * callback's error. If not, use the original error. */ @@ -3015,7 +3090,14 @@ connect_done (MMAtSerialPort *port, gpointer user_data) { MMCallbackInfo *info = (MMCallbackInfo *) user_data; - MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); + MMGenericGsmPrivate *priv; + + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + + priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); if (error) { info->error = g_error_copy (error); @@ -3067,15 +3149,17 @@ disconnect_done (MMModem *modem, MMCallbackInfo *info = (MMCallbackInfo *) user_data; MMModemState prev_state; - info->error = mm_modem_check_removed (modem, error); - if (info->error) { - if (info->modem && modem) { - /* Reset old state since the operation failed */ - prev_state = GPOINTER_TO_UINT (mm_callback_info_get_data (info, MM_GENERIC_GSM_PREV_STATE_TAG)); - mm_modem_set_state (MM_MODEM (info->modem), - prev_state, - MM_MODEM_STATE_REASON_NONE); - } + /* Do nothing if modem removed */ + if (!modem || mm_callback_info_check_modem_removed (info)) + return; + + if (error) { + info->error = g_error_copy (error); + /* Reset old state since the operation failed */ + prev_state = GPOINTER_TO_UINT (mm_callback_info_get_data (info, MM_GENERIC_GSM_PREV_STATE_TAG)); + mm_modem_set_state (MM_MODEM (info->modem), + prev_state, + MM_MODEM_STATE_REASON_NONE); } else { MMGenericGsm *self = MM_GENERIC_GSM (modem); MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); @@ -3094,7 +3178,14 @@ disconnect_all_done (MMAtSerialPort *port, GError *error, gpointer user_data) { - mm_callback_info_schedule ((MMCallbackInfo *) user_data); + MMCallbackInfo *info = (MMCallbackInfo *)user_data; + + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + + mm_callback_info_schedule (info); } static void @@ -3126,17 +3217,21 @@ disconnect_flash_done (MMSerialPort *port, MMCallbackInfo *info = (MMCallbackInfo *) user_data; MMGenericGsmPrivate *priv; - info->error = mm_modem_check_removed (info->modem, error); - if (info->error) { + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + + if (error) { /* Ignore "NO CARRIER" response when modem disconnects and any flash * failures we might encounter. Other errors are hard errors. */ - if ( !g_error_matches (info->error, MM_MODEM_CONNECT_ERROR, MM_MODEM_CONNECT_ERROR_NO_CARRIER) - && !g_error_matches (info->error, MM_SERIAL_ERROR, MM_SERIAL_ERROR_FLASH_FAILED)) { + if ( !g_error_matches (error, MM_MODEM_CONNECT_ERROR, MM_MODEM_CONNECT_ERROR_NO_CARRIER) + && !g_error_matches (error, MM_SERIAL_ERROR, MM_SERIAL_ERROR_FLASH_FAILED)) { + info->error = g_error_copy (error); mm_callback_info_schedule (info); return; } - g_clear_error (&info->error); } priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); @@ -3163,11 +3258,10 @@ disconnect_secondary_cgact_done (MMAtSerialPort *port, MMGenericGsm *self; MMGenericGsmPrivate *priv; - if (!info->modem) { - info->error = mm_modem_check_removed (info->modem, error); - mm_callback_info_schedule (info); + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) return; - } self = MM_GENERIC_GSM (info->modem); priv = MM_GENERIC_GSM_GET_PRIVATE (self); @@ -3257,6 +3351,11 @@ scan_done (MMAtSerialPort *port, MMCallbackInfo *info = (MMCallbackInfo *) user_data; GPtrArray *results; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + if (error) info->error = g_error_copy (error); else { @@ -3296,8 +3395,14 @@ set_apn_done (MMAtSerialPort *port, { MMCallbackInfo *info = (MMCallbackInfo *) user_data; - info->error = mm_modem_check_removed (info->modem, error); - if (!info->error) { + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + + if (error) + info->error = g_error_copy (error); + else { MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); priv->cid = GPOINTER_TO_INT (mm_callback_info_get_data (info, APN_CID_TAG)); @@ -3315,6 +3420,11 @@ cid_range_read (MMAtSerialPort *port, MMCallbackInfo *info = (MMCallbackInfo *) user_data; guint32 cid = 0; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + if (error) info->error = g_error_copy (error); else if (g_str_has_prefix (response->str, "+CGDCONT:")) { @@ -3381,10 +3491,14 @@ existing_apns_read (MMAtSerialPort *port, MMCallbackInfo *info = (MMCallbackInfo *) user_data; gboolean found = FALSE; - info->error = mm_modem_check_removed (info->modem, error); - if (info->error) - goto done; - else if (g_str_has_prefix (response->str, "+CGDCONT:")) { + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + + if (error) { + info->error = g_error_copy (error); + } else if (g_str_has_prefix (response->str, "+CGDCONT:")) { GRegex *r; GMatchInfo *match_info; @@ -3435,7 +3549,6 @@ existing_apns_read (MMAtSerialPort *port, MM_MODEM_ERROR_GENERAL, "Could not parse the response"); -done: if (found || info->error) mm_callback_info_schedule (info); else { @@ -3542,8 +3655,14 @@ get_cind_signal_done (MMAtSerialPort *port, GByteArray *indicators; guint quality; - info->error = mm_modem_check_removed (info->modem, error); - if (!info->error) { + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + + if (error) + info->error = g_error_copy (error); + else { priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); indicators = mm_parse_cind_query_response (response->str, &info->error); @@ -3571,9 +3690,15 @@ get_csq_done (MMAtSerialPort *port, char *reply = response->str; gboolean parsed = FALSE; - info->error = mm_modem_check_removed (info->modem, error); - if (info->error) + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + + if (error) { + info->error = g_error_copy (error); goto done; + } if (!strncmp (reply, "+CSQ: ", 6)) { /* Got valid reply */ @@ -3721,8 +3846,13 @@ set_allowed_mode_done (MMModem *modem, GError *error, gpointer user_data) { MMCallbackInfo *info = user_data; - info->error = mm_modem_check_removed (info->modem, error); - if (!info->error) { + /* Do nothing if modem removed */ + if (!modem || mm_callback_info_check_modem_removed (info)) + return; + + if (error) + info->error = g_error_copy (error); + else { MMModemGsmAllowedMode mode = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "mode")); mm_generic_gsm_update_allowed_mode (MM_GENERIC_GSM (info->modem), mode); @@ -3777,8 +3907,13 @@ get_charsets_done (MMAtSerialPort *port, MMCallbackInfo *info = (MMCallbackInfo *) user_data; MMGenericGsmPrivate *priv; - info->error = mm_modem_check_removed (info->modem, error); - if (info->error) { + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + + if (error) { + info->error = g_error_copy (error); mm_callback_info_schedule (info); return; } @@ -3836,8 +3971,13 @@ set_get_charset_done (MMAtSerialPort *port, MMModemCharset tried_charset; const char *p; - info->error = mm_modem_check_removed (info->modem, error); - if (info->error) { + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + + if (error) { + info->error = g_error_copy (error); mm_callback_info_schedule (info); return; } @@ -3873,13 +4013,18 @@ set_charset_done (MMAtSerialPort *port, { MMCallbackInfo *info = (MMCallbackInfo *) user_data; - info->error = mm_modem_check_removed (info->modem, error); - if (info->error) { + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + + if (error) { gboolean tried_no_quotes = !!mm_callback_info_get_data (info, TRIED_NO_QUOTES_TAG); MMModemCharset charset = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "charset")); char *command; - if (!info->modem || tried_no_quotes) { + if (tried_no_quotes) { + info->error = g_error_copy (error); mm_callback_info_schedule (info); return; } @@ -3992,6 +4137,11 @@ sms_send_done (MMAtSerialPort *port, { MMCallbackInfo *info = (MMCallbackInfo *) user_data; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + if (error) info->error = g_error_copy (error); @@ -4253,6 +4403,11 @@ sms_get_done (MMAtSerialPort *port, int rv, status, tpdu_len, offset; char pdu[SMS_MAX_PDU_LEN + 1]; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + if (error) { info->error = g_error_copy (error); goto out; @@ -4327,6 +4482,11 @@ sms_delete_done (MMAtSerialPort *port, { MMCallbackInfo *info = (MMCallbackInfo *) user_data; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + if (error) info->error = g_error_copy (error); @@ -4368,6 +4528,11 @@ sms_list_done (MMAtSerialPort *port, int rv, status, tpdu_len, offset; char *rstr; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + if (error) info->error = g_error_copy (error); else { @@ -4506,6 +4671,11 @@ ussd_send_done (MMAtSerialPort *port, const char *str, *start = NULL, *end = NULL; char *reply = NULL, *converted; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + if (error) { info->error = g_error_copy (error); goto done; @@ -4664,13 +4834,17 @@ ussd_cancel_done (MMAtSerialPort *port, { MMCallbackInfo *info = (MMCallbackInfo *) user_data; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + if (error) info->error = g_error_copy (error); mm_callback_info_schedule (info); - if (info->modem) - ussd_update_state (MM_GENERIC_GSM (info->modem), MM_MODEM_GSM_USSD_STATE_IDLE); + ussd_update_state (MM_GENERIC_GSM (info->modem), MM_MODEM_GSM_USSD_STATE_IDLE); } static void @@ -4828,9 +5002,14 @@ simple_state_machine (MMModem *modem, GError *error, gpointer user_data) gboolean home_only = FALSE; char *data_device; - info->error = mm_modem_check_removed (modem, error); - if (info->error) + /* Do nothing if modem removed */ + if (!modem || mm_callback_info_check_modem_removed (info)) + return; + + if (error) { + info->error = g_error_copy (error); goto out; + } priv = MM_GENERIC_GSM_GET_PRIVATE (modem); @@ -5047,8 +5226,13 @@ simple_status_got_reg_info (MMModemGsmNetwork *modem, MMCallbackInfo *info = (MMCallbackInfo *) user_data; GHashTable *properties; - info->error = mm_modem_check_removed ((MMModem *) modem, error); - if (!info->error) { + /* Do nothing if modem removed */ + if (!modem || mm_callback_info_check_modem_removed (info)) + return; + + if (error) + info->error = g_error_copy (error); + else { properties = (GHashTable *) mm_callback_info_get_data (info, SS_HASH_TAG); g_hash_table_insert (properties, "registration_status", simple_uint_value (status)); diff --git a/src/mm-modem-base.c b/src/mm-modem-base.c index 9afc1bf9..451e2ebe 100644 --- a/src/mm-modem-base.c +++ b/src/mm-modem-base.c @@ -493,15 +493,17 @@ info_item_done (MMCallbackInfo *info, mm_callback_info_chain_complete_one (info); } -#define GET_INFO_RESP_FN(func_name, tag, tag2, desc) \ -static void \ -func_name (MMAtSerialPort *port, \ - GString *response, \ - GError *error, \ - gpointer user_data) \ -{ \ - info_item_done ((MMCallbackInfo *) user_data, response, error, tag, tag2, desc ); \ -} +#define GET_INFO_RESP_FN(func_name, tag, tag2, desc) \ + static void \ + func_name (MMAtSerialPort *port, \ + GString *response, \ + GError *error, \ + gpointer user_data) \ + { \ + if (mm_callback_info_check_modem_removed ((MMCallbackInfo *) user_data)) \ + return; \ + info_item_done ((MMCallbackInfo *) user_data, response, error, tag, tag2, desc ); \ + } GET_INFO_RESP_FN(get_revision_done, "+GMR:", "AT+GMR", "card-info-revision") GET_INFO_RESP_FN(get_model_done, "+GMM:", "AT+GMM", "card-info-model") diff --git a/src/mm-modem.c b/src/mm-modem.c index d5351660..b3c1677d 100644 --- a/src/mm-modem.c +++ b/src/mm-modem.c @@ -33,25 +33,6 @@ static void impl_modem_factory_reset (MMModem *modem, const char *code, DBusGMet #include "mm-modem-glue.h" -/* Should be used from callbacks to check whether the modem was removed after - * the callback's operation was started, but before the callback itself was - * called, in which case the MMModem passed to the callback is NULL. - */ -GError * -mm_modem_check_removed (MMModem *self, const GError *error) -{ - if (!self) { - /* If the modem was NULL, the error *should* have been - * MM_MODEM_ERROR_REMOVED. If it wasn't, make it that. - */ - return g_error_new_literal (MM_MODEM_ERROR, - MM_MODEM_ERROR_REMOVED, - "The modem was removed."); - } - - return error ? g_error_copy (error) : NULL; -} - static void async_op_not_supported (MMModem *self, MMModemFn callback, diff --git a/src/mm-modem.h b/src/mm-modem.h index c478f701..45f81103 100644 --- a/src/mm-modem.h +++ b/src/mm-modem.h @@ -282,8 +282,6 @@ void mm_modem_set_state (MMModem *self, MMModemState new_state, MMModemStateReason reason); -GError *mm_modem_check_removed (MMModem *self, const GError *error); - /* Request authorization to perform an action. Used by D-Bus method * handlers to ensure that the incoming request is authorized to perform * the action it's requesting. |