mirror of git://git.sysmocom.de/ofono
gatchat: Fix calling unregister from callbacks
This fixes the issues with SIM hotswap on infineon
This commit is contained in:
parent
167c72e588
commit
1e1ddfcf1b
|
@ -61,6 +61,7 @@ struct at_notify_node {
|
|||
GAtNotifyFunc callback;
|
||||
gpointer user_data;
|
||||
GDestroyNotify notify;
|
||||
gboolean destroyed;
|
||||
};
|
||||
|
||||
typedef gboolean (*node_remove_func)(struct at_notify_node *node,
|
||||
|
@ -96,6 +97,7 @@ struct at_chat {
|
|||
GAtSyntax *syntax;
|
||||
gboolean destroyed; /* Re-entrancy guard */
|
||||
gboolean in_read_handler; /* Re-entrancy guard */
|
||||
gboolean in_notify;
|
||||
GSList *terminator_list; /* Non-standard terminator */
|
||||
};
|
||||
|
||||
|
@ -111,6 +113,11 @@ struct terminator_info {
|
|||
gboolean success;
|
||||
};
|
||||
|
||||
static gboolean node_is_destroyed(struct at_notify_node *node, gpointer user)
|
||||
{
|
||||
return node->destroyed;
|
||||
}
|
||||
|
||||
static gint at_notify_node_compare_by_id(gconstpointer a, gconstpointer b)
|
||||
{
|
||||
const struct at_notify_node *node = a;
|
||||
|
@ -158,6 +165,7 @@ static gint at_command_compare_by_id(gconstpointer a, gconstpointer b)
|
|||
}
|
||||
|
||||
static gboolean at_chat_unregister_all(struct at_chat *chat,
|
||||
gboolean mark_only,
|
||||
node_remove_func func,
|
||||
gpointer userdata)
|
||||
{
|
||||
|
@ -189,6 +197,13 @@ static gboolean at_chat_unregister_all(struct at_chat *chat,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (mark_only) {
|
||||
node->destroyed = TRUE;
|
||||
p = c;
|
||||
c = c->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (p)
|
||||
p->next = c->next;
|
||||
else
|
||||
|
@ -375,6 +390,8 @@ static gboolean at_chat_match_notify(struct at_chat *chat, char *line)
|
|||
result.lines = 0;
|
||||
result.final_or_pdu = 0;
|
||||
|
||||
chat->in_notify = TRUE;
|
||||
|
||||
while (g_hash_table_iter_next(&iter, &key, &value)) {
|
||||
notify = value;
|
||||
|
||||
|
@ -398,9 +415,13 @@ static gboolean at_chat_match_notify(struct at_chat *chat, char *line)
|
|||
ret = TRUE;
|
||||
}
|
||||
|
||||
chat->in_notify = FALSE;
|
||||
|
||||
if (ret) {
|
||||
g_slist_free(result.lines);
|
||||
g_free(line);
|
||||
|
||||
at_chat_unregister_all(chat, FALSE, node_is_destroyed, NULL);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -584,6 +605,9 @@ static void have_notify_pdu(struct at_chat *p, char *pdu, GAtResult *result)
|
|||
struct at_notify *notify;
|
||||
char *prefix;
|
||||
gpointer key, value;
|
||||
gboolean called = FALSE;
|
||||
|
||||
p->in_notify = TRUE;
|
||||
|
||||
g_hash_table_iter_init(&iter, p->notify_list);
|
||||
|
||||
|
@ -598,7 +622,13 @@ static void have_notify_pdu(struct at_chat *p, char *pdu, GAtResult *result)
|
|||
continue;
|
||||
|
||||
g_slist_foreach(notify->nodes, at_notify_call_callback, result);
|
||||
called = TRUE;
|
||||
}
|
||||
|
||||
p->in_notify = FALSE;
|
||||
|
||||
if (called)
|
||||
at_chat_unregister_all(p, FALSE, node_is_destroyed, NULL);
|
||||
}
|
||||
|
||||
static void have_pdu(struct at_chat *p, char *pdu)
|
||||
|
@ -1114,7 +1144,8 @@ static guint at_chat_register(struct at_chat *chat, guint group,
|
|||
return node->id;
|
||||
}
|
||||
|
||||
static gboolean at_chat_unregister(struct at_chat *chat, guint group, guint id)
|
||||
static gboolean at_chat_unregister(struct at_chat *chat, gboolean mark_only,
|
||||
guint group, guint id)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
struct at_notify *notify;
|
||||
|
@ -1141,6 +1172,11 @@ static gboolean at_chat_unregister(struct at_chat *chat, guint group, guint id)
|
|||
if (node->gid != group)
|
||||
return FALSE;
|
||||
|
||||
if (mark_only) {
|
||||
node->destroyed = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
at_notify_node_destroy(node, NULL);
|
||||
notify->nodes = g_slist_remove(notify->nodes, node);
|
||||
|
||||
|
@ -1439,7 +1475,8 @@ gboolean g_at_chat_unregister(GAtChat *chat, guint id)
|
|||
if (chat == NULL)
|
||||
return FALSE;
|
||||
|
||||
return at_chat_unregister(chat->parent, chat->group, id);
|
||||
return at_chat_unregister(chat->parent, chat->parent->in_notify,
|
||||
chat->group, id);
|
||||
}
|
||||
|
||||
gboolean g_at_chat_unregister_all(GAtChat *chat)
|
||||
|
@ -1448,6 +1485,7 @@ gboolean g_at_chat_unregister_all(GAtChat *chat)
|
|||
return FALSE;
|
||||
|
||||
return at_chat_unregister_all(chat->parent,
|
||||
chat->parent->in_notify,
|
||||
node_compare_by_group,
|
||||
GUINT_TO_POINTER(chat->group));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue