summaryrefslogtreecommitdiffstats
path: root/gatchat/gathdlc.c
diff options
context:
space:
mode:
authorDenis Kenzior <denkenz@gmail.com>2010-06-18 12:23:10 -0500
committerDenis Kenzior <denkenz@gmail.com>2010-06-18 12:23:10 -0500
commitab76f57cf9a889a654f8e1591b7260d81f9de228 (patch)
tree43e898b51ba53605b83c4a91ec6d33ab8e8e8286 /gatchat/gathdlc.c
parente2e17512e0666f322bc5f833e48f12b51fb0027e (diff)
downloadofono-ab76f57cf9a889a654f8e1591b7260d81f9de228.tar.bz2
gathdlc: Don't crash if unreffed in callback
Diffstat (limited to 'gatchat/gathdlc.c')
-rw-r--r--gatchat/gathdlc.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/gatchat/gathdlc.c b/gatchat/gathdlc.c
index 8c85c7bd..9624bbd7 100644
--- a/gatchat/gathdlc.c
+++ b/gatchat/gathdlc.c
@@ -64,6 +64,8 @@ struct _GAtHDLC {
GAtDebugFunc debugf;
gpointer debug_data;
int record_fd;
+ gboolean in_read_handler;
+ gboolean destroyed;
};
static void hdlc_record(int fd, gboolean in, guint8 *data, guint16 length)
@@ -133,6 +135,8 @@ static void new_bytes(struct ring_buffer *rbuf, gpointer user_data)
hdlc_record(hdlc->record_fd, TRUE, buf, wrap);
+ hdlc->in_read_handler = TRUE;
+
while (pos < len) {
if (hdlc->decode_escape == TRUE) {
unsigned char val = *buf ^ HDLC_TRANS;
@@ -149,6 +153,9 @@ static void new_bytes(struct ring_buffer *rbuf, gpointer user_data)
hdlc->receive_func(hdlc->decode_buffer,
hdlc->decode_offset - 2,
hdlc->receive_data);
+
+ if (hdlc->destroyed)
+ goto out;
}
hdlc->decode_fcs = HDLC_INITFCS;
@@ -169,6 +176,12 @@ static void new_bytes(struct ring_buffer *rbuf, gpointer user_data)
}
ring_buffer_drain(rbuf, pos);
+
+out:
+ hdlc->in_read_handler = FALSE;
+
+ if (hdlc->destroyed)
+ g_free(hdlc);
}
GAtHDLC *g_at_hdlc_new_from_io(GAtIO *io)
@@ -267,7 +280,11 @@ void g_at_hdlc_unref(GAtHDLC *hdlc)
ring_buffer_free(hdlc->write_buffer);
g_free(hdlc->decode_buffer);
- g_free(hdlc);
+
+ if (hdlc->in_read_handler)
+ hdlc->destroyed = TRUE;
+ else
+ g_free(hdlc);
}
void g_at_hdlc_set_debug(GAtHDLC *hdlc, GAtDebugFunc func, gpointer user_data)