diff options
author | Denis Kenzior <denkenz@gmail.com> | 2010-04-27 20:07:47 -0500 |
---|---|---|
committer | Denis Kenzior <denkenz@gmail.com> | 2010-04-28 17:27:34 -0500 |
commit | 033b57659325b932a708520eeac5ef980401c872 (patch) | |
tree | 6c83a2d0104d7c6fff5a15031c64f6a97c692dba /gatchat/gatchat.c | |
parent | 9c3ae4746e13145dd0c75d08d56e3c3714cdfcf3 (diff) | |
download | ofono-033b57659325b932a708520eeac5ef980401c872.tar.bz2 |
gatchat: Better re-entrancy handling
Diffstat (limited to 'gatchat/gatchat.c')
-rw-r--r-- | gatchat/gatchat.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/gatchat/gatchat.c b/gatchat/gatchat.c index ac45890b..4b86ed45 100644 --- a/gatchat/gatchat.c +++ b/gatchat/gatchat.c @@ -91,6 +91,7 @@ struct _GAtChat { GTimer *wakeup_timer; /* Keep track of elapsed time */ GAtSyntax *syntax; gboolean destroyed; /* Re-entrancy guard */ + gboolean in_read_handler; /* Re-entrancy guard */ GSList *terminator_list; /* Non-standard terminator */ }; @@ -229,7 +230,7 @@ static void free_terminator(struct terminator_info *info) info = NULL; } -static void g_at_chat_cleanup(GAtChat *chat) +static void chat_cleanup(GAtChat *chat) { struct at_command *c; @@ -289,7 +290,7 @@ static void io_disconnect(gpointer user_data) g_at_io_set_read_handler(chat->io, NULL, NULL); g_at_io_unref(chat->io); - g_at_chat_cleanup(chat); + chat_cleanup(chat); if (chat->user_disconnect) chat->user_disconnect(chat->user_disconnect_data); @@ -637,7 +638,7 @@ static void new_bytes(struct ring_buffer *rbuf, gpointer user_data) GAtSyntaxResult result; - g_at_chat_ref(p); + p->in_read_handler = TRUE; while (p->suspended == FALSE && (p->read_so_far < len)) { gsize rbytes = MIN(len - p->read_so_far, wrap - p->read_so_far); @@ -679,7 +680,10 @@ static void new_bytes(struct ring_buffer *rbuf, gpointer user_data) p->read_so_far = 0; } - g_at_chat_unref(p); + p->in_read_handler = FALSE; + + if (p->destroyed) + g_free(p); } static void wakeup_cb(gboolean ok, GAtResult *result, gpointer user_data) @@ -974,9 +978,12 @@ void g_at_chat_unref(GAtChat *chat) g_at_chat_suspend(chat); g_at_io_unref(chat->io); - g_at_chat_cleanup(chat); + chat_cleanup(chat); - g_free(chat); + if (chat->in_read_handler) + chat->destroyed = TRUE; + else + g_free(chat); } gboolean g_at_chat_set_disconnect_function(GAtChat *chat, |