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:
@@ -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 */
|
||||
|
Reference in New Issue
Block a user