Diff between cff3015e5ad3c62571dc5bcce23acc298ad6c6ca and e32f2f1ada69ae6fda182e87b72da874019b4125

Changed Files

File Additions Deletions Status
src/shared/io-glib.c +39 -6 modified

Full Patch

diff --git a/src/shared/io-glib.c b/src/shared/io-glib.c
index ea84a69..488b1a2 100644
--- a/src/shared/io-glib.c
+++ b/src/shared/io-glib.c
@@ -30,6 +30,7 @@
 #include "src/shared/io.h"
 
 struct io {
+	int ref_count;
 	GIOChannel *channel;
 	guint read_watch;
 	io_callback_func_t read_callback;
@@ -41,6 +42,27 @@ struct io {
 	void *write_data;
 };
 
+static struct io *io_ref(struct io *io)
+{
+	if (!io)
+		return NULL;
+
+	__sync_fetch_and_add(&io->ref_count, 1);
+
+	return io;
+}
+
+static void io_unref(struct io *io)
+{
+	if (!io)
+		return;
+
+	if (__sync_sub_and_fetch(&io->ref_count, 1))
+		return;
+
+	g_free(io);
+}
+
 struct io *io_new(int fd)
 {
 	struct io *io;
@@ -69,7 +91,7 @@ struct io *io_new(int fd)
 	io->write_destroy = NULL;
 	io->write_data = NULL;
 
-	return io;
+	return io_ref(io);
 }
 
 void io_destroy(struct io *io)
@@ -77,15 +99,20 @@ void io_destroy(struct io *io)
 	if (!io)
 		return;
 
-	if (io->read_watch > 0)
+	if (io->read_watch > 0) {
 		g_source_remove(io->read_watch);
+		io->read_watch = 0;
+	}
 
-	if (io->write_watch > 0)
+	if (io->write_watch > 0) {
 		g_source_remove(io->write_watch);
+		io->write_watch = 0;
+	}
 
 	g_io_channel_unref(io->channel);
+	io->channel = NULL;
 
-	g_free(io);
+	io_unref(io);
 }
 
 int io_get_fd(struct io *io)
@@ -120,6 +147,8 @@ static void read_watch_destroy(gpointer user_data)
 	io->read_callback = NULL;
 	io->read_destroy = NULL;
 	io->read_data = NULL;
+
+	io_unref(io);
 }
 
 static gboolean read_callback(GIOChannel *channel, GIOCondition cond,
@@ -155,7 +184,8 @@ bool io_set_read_handler(struct io *io, io_callback_func_t callback,
 
 	io->read_watch = g_io_add_watch_full(io->channel, G_PRIORITY_DEFAULT,
 				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
-				read_callback, io, read_watch_destroy);
+				read_callback, io_ref(io),
+				read_watch_destroy);
 	if (io->read_watch == 0)
 		return false;
 
@@ -178,6 +208,8 @@ static void write_watch_destroy(gpointer user_data)
 	io->write_callback = NULL;
 	io->write_destroy = NULL;
 	io->write_data = NULL;
+
+	io_unref(io);
 }
 
 static gboolean write_callback(GIOChannel *channel, GIOCondition cond,
@@ -213,7 +245,8 @@ bool io_set_write_handler(struct io *io, io_callback_func_t callback,
 
 	io->write_watch = g_io_add_watch_full(io->channel, G_PRIORITY_DEFAULT,
 				G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
-				write_callback, io, write_watch_destroy);
+				write_callback, io_ref(io),
+				write_watch_destroy);
 	if (io->write_watch == 0)
 		return false;