aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2010-03-09 10:20:32 -0800
committerDan Williams <dcbw@redhat.com>2010-03-09 10:20:32 -0800
commit2f925599c089484286a08ce84885b0385bcd64d2 (patch)
tree32635ad435d35f4da86d47f6a628d2d76b78c7d7 /src
parent783de3bc10ba8b6fe934887efaeb229da6ad9d06 (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.c71
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 */