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.
This commit is contained in:
Dan Williams
2010-03-09 10:20:32 -08:00
parent 783de3bc10
commit 2f925599c0

View File

@@ -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, 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);
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);
/* 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 */