diff options
author | Dan Williams <dcbw@redhat.com> | 2010-03-09 10:20:32 -0800 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2010-03-09 10:20:32 -0800 |
commit | 2f925599c089484286a08ce84885b0385bcd64d2 (patch) | |
tree | 32635ad435d35f4da86d47f6a628d2d76b78c7d7 /src | |
parent | 783de3bc10ba8b6fe934887efaeb229da6ad9d06 (diff) |
gsm: fix crash in Simple API's GetStatus handling
Can't schedule the info completion until we're sure all the
requests have completed. They won't necessarily be completed
in the same order they were issued since some of the data the
requests pull from could be cached and thus we don't have to
wait in the queue to hit up the modem.
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-generic-gsm.c | 71 |
1 files changed, 49 insertions, 22 deletions
diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index b2794e21..53406b15 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -2504,8 +2504,6 @@ simple_connect (MMModemSimple *simple, simple_state_machine (MM_MODEM (simple), NULL, info); } - - static void simple_free_gvalue (gpointer data) { @@ -2537,16 +2535,39 @@ simple_string_value (const char *str) return val; } +#define NOTDONE_TAG "not-done" +#define SS_HASH_TAG "simple-get-status" + +static void +simple_status_complete_item (MMCallbackInfo *info) +{ + guint32 completed = GPOINTER_TO_UINT (mm_callback_info_get_data (info, NOTDONE_TAG)); + + g_warn_if_fail (completed > 0); + + /* Decrement the number of outstanding calls and if there aren't any left, + * schedule the callback info completion. + */ + completed--; + mm_callback_info_set_data (info, NOTDONE_TAG, GUINT_TO_POINTER (completed), NULL); + if (completed == 0) + mm_callback_info_schedule (info); +} + static void simple_status_got_signal_quality (MMModem *modem, guint32 result, GError *error, gpointer user_data) { - if (error) - g_warning ("Error getting signal quality: %s", error->message); - else - g_hash_table_insert ((GHashTable *) user_data, "signal_quality", simple_uint_value (result)); + MMCallbackInfo *info = (MMCallbackInfo *) user_data; + GHashTable *properties; + + if (!error) { + properties = (GHashTable *) mm_callback_info_get_data (info, SS_HASH_TAG); + g_hash_table_insert (properties, "signal_quality", simple_uint_value (result)); + } + simple_status_complete_item (info); } static void @@ -2555,9 +2576,14 @@ simple_status_got_band (MMModem *modem, GError *error, gpointer user_data) { - /* Ignore band errors since there's no generic implementation for it */ - if (!error) - g_hash_table_insert ((GHashTable *) user_data, "band", simple_uint_value (result)); + MMCallbackInfo *info = (MMCallbackInfo *) user_data; + GHashTable *properties; + + if (!error) { + properties = (GHashTable *) mm_callback_info_get_data (info, SS_HASH_TAG); + g_hash_table_insert (properties, "band", simple_uint_value (result)); + } + simple_status_complete_item (info); } static void @@ -2571,17 +2597,15 @@ simple_status_got_reg_info (MMModemGsmNetwork *modem, MMCallbackInfo *info = (MMCallbackInfo *) user_data; GHashTable *properties; - if (error) - info->error = g_error_copy (error); - else { - properties = (GHashTable *) mm_callback_info_get_data (info, "simple-get-status"); - + info->error = mm_modem_check_removed ((MMModem *) modem, error); + if (!info->error) { + properties = (GHashTable *) mm_callback_info_get_data (info, SS_HASH_TAG); + g_hash_table_insert (properties, "registration_status", simple_uint_value (status)); g_hash_table_insert (properties, "operator_code", simple_string_value (oper_code)); g_hash_table_insert (properties, "operator_name", simple_string_value (oper_name)); } - - mm_callback_info_schedule (info); + simple_status_complete_item (info); } static void @@ -2590,7 +2614,7 @@ simple_get_status_invoke (MMCallbackInfo *info) MMModemSimpleGetStatusFn callback = (MMModemSimpleGetStatusFn) info->callback; callback (MM_MODEM_SIMPLE (info->modem), - (GHashTable *) mm_callback_info_get_data (info, "simple-get-status"), + (GHashTable *) mm_callback_info_get_data (info, SS_HASH_TAG), info->error, info->user_data); } @@ -2610,12 +2634,15 @@ simple_get_status (MMModemSimple *simple, G_CALLBACK (callback), user_data); - properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, simple_free_gvalue); - mm_callback_info_set_data (info, "simple-get-status", properties, (GDestroyNotify) g_hash_table_unref); + properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, simple_free_gvalue); + mm_callback_info_set_data (info, SS_HASH_TAG, properties, (GDestroyNotify) g_hash_table_unref); + + mm_modem_gsm_network_get_signal_quality (gsm, simple_status_got_signal_quality, info); + mm_modem_gsm_network_get_band (gsm, simple_status_got_band, info); + mm_modem_gsm_network_get_registration_info (gsm, simple_status_got_reg_info, info); - mm_modem_gsm_network_get_signal_quality (gsm, simple_status_got_signal_quality, properties); - mm_modem_gsm_network_get_band (gsm, simple_status_got_band, properties); - mm_modem_gsm_network_get_registration_info (gsm, simple_status_got_reg_info, properties); + /* 3 calls to complete before scheduling the callback: (signal, band, reginfo) */ + mm_callback_info_set_data (info, NOTDONE_TAG, GUINT_TO_POINTER (3), NULL); if (priv->act > -1) { /* Deprecated key */ |