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);
|
simple_state_machine (MM_MODEM (simple), NULL, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
simple_free_gvalue (gpointer data)
|
simple_free_gvalue (gpointer data)
|
||||||
{
|
{
|
||||||
@@ -2537,16 +2535,39 @@ simple_string_value (const char *str)
|
|||||||
return val;
|
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
|
static void
|
||||||
simple_status_got_signal_quality (MMModem *modem,
|
simple_status_got_signal_quality (MMModem *modem,
|
||||||
guint32 result,
|
guint32 result,
|
||||||
GError *error,
|
GError *error,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
if (error)
|
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||||
g_warning ("Error getting signal quality: %s", error->message);
|
GHashTable *properties;
|
||||||
else
|
|
||||||
g_hash_table_insert ((GHashTable *) user_data, "signal_quality", simple_uint_value (result));
|
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
|
static void
|
||||||
@@ -2555,9 +2576,14 @@ simple_status_got_band (MMModem *modem,
|
|||||||
GError *error,
|
GError *error,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
/* Ignore band errors since there's no generic implementation for it */
|
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||||
if (!error)
|
GHashTable *properties;
|
||||||
g_hash_table_insert ((GHashTable *) user_data, "band", simple_uint_value (result));
|
|
||||||
|
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
|
static void
|
||||||
@@ -2571,17 +2597,15 @@ simple_status_got_reg_info (MMModemGsmNetwork *modem,
|
|||||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||||
GHashTable *properties;
|
GHashTable *properties;
|
||||||
|
|
||||||
if (error)
|
info->error = mm_modem_check_removed ((MMModem *) modem, error);
|
||||||
info->error = g_error_copy (error);
|
if (!info->error) {
|
||||||
else {
|
properties = (GHashTable *) mm_callback_info_get_data (info, SS_HASH_TAG);
|
||||||
properties = (GHashTable *) mm_callback_info_get_data (info, "simple-get-status");
|
|
||||||
|
|
||||||
g_hash_table_insert (properties, "registration_status", simple_uint_value (status));
|
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_code", simple_string_value (oper_code));
|
||||||
g_hash_table_insert (properties, "operator_name", simple_string_value (oper_name));
|
g_hash_table_insert (properties, "operator_name", simple_string_value (oper_name));
|
||||||
}
|
}
|
||||||
|
simple_status_complete_item (info);
|
||||||
mm_callback_info_schedule (info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -2590,7 +2614,7 @@ simple_get_status_invoke (MMCallbackInfo *info)
|
|||||||
MMModemSimpleGetStatusFn callback = (MMModemSimpleGetStatusFn) info->callback;
|
MMModemSimpleGetStatusFn callback = (MMModemSimpleGetStatusFn) info->callback;
|
||||||
|
|
||||||
callback (MM_MODEM_SIMPLE (info->modem),
|
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);
|
info->error, info->user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2610,12 +2634,15 @@ simple_get_status (MMModemSimple *simple,
|
|||||||
G_CALLBACK (callback),
|
G_CALLBACK (callback),
|
||||||
user_data);
|
user_data);
|
||||||
|
|
||||||
properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, simple_free_gvalue);
|
properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, simple_free_gvalue);
|
||||||
mm_callback_info_set_data (info, "simple-get-status", properties, (GDestroyNotify) g_hash_table_unref);
|
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_signal_quality (gsm, simple_status_got_signal_quality, info);
|
||||||
mm_modem_gsm_network_get_band (gsm, simple_status_got_band, properties);
|
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, properties);
|
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) {
|
if (priv->act > -1) {
|
||||||
/* Deprecated key */
|
/* Deprecated key */
|
||||||
|
Reference in New Issue
Block a user