summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@codefactory.se>2003-08-05 13:57:20 +0000
committerAnders Carlsson <andersca@codefactory.se>2003-08-05 13:57:20 +0000
commit1efd75a5d8502f644ef6f71bc295d85c47551426 (patch)
tree256248ee00d6547ef080d6865af05580c287a601
parent29b65fa3237afe07cdf8acaa9d46c92dbe749fb2 (diff)
2003-08-05 Anders Carlsson <andersca@codefactory.se>
* glib/dbus-gmain.c: (watch_fd_new), (watch_fd_ref), (watch_fd_unref), (dbus_gsource_check), (dbus_gsource_dispatch), (add_watch), (remove_watch), (create_source): Refcount fds, fixes some reentrancy issues.
-rw-r--r--ChangeLog7
-rw-r--r--glib/dbus-gmain.c116
2 files changed, 85 insertions, 38 deletions
diff --git a/ChangeLog b/ChangeLog
index 1980a4c6..3a963e05 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2003-08-05 Anders Carlsson <andersca@codefactory.se>
+
+ * glib/dbus-gmain.c: (watch_fd_new), (watch_fd_ref),
+ (watch_fd_unref), (dbus_gsource_check), (dbus_gsource_dispatch),
+ (add_watch), (remove_watch), (create_source):
+ Refcount fds, fixes some reentrancy issues.
+
2003-07-30 Havoc Pennington <hp@redhat.com>
* dbus/dbus-bus.c (init_connections_unlocked): fix default system
diff --git a/glib/dbus-gmain.c b/glib/dbus-gmain.c
index 9b14049d..d948b431 100644
--- a/glib/dbus-gmain.c
+++ b/glib/dbus-gmain.c
@@ -52,14 +52,53 @@ struct DBusGSource
{
GSource source; /**< the parent GSource */
- GList *poll_fds; /**< descriptors we're watching */
- GHashTable *watches; /**< hash of DBusWatch objects */
+ GList *watch_fds; /**< descriptors we're watching */
GMainContext *context; /**< the GMainContext to use, NULL for default */
void *connection_or_server; /**< DBusConnection or DBusServer */
};
+typedef struct
+{
+ int refcount;
+
+ GPollFD poll_fd;
+ DBusWatch *watch;
+
+ unsigned int removed : 1;
+} WatchFD;
+
+static WatchFD *
+watch_fd_new (void)
+{
+ WatchFD *watch_fd;
+
+ watch_fd = g_new0 (WatchFD, 1);
+ watch_fd->refcount = 1;
+
+ return watch_fd;
+}
+
+static void
+watch_fd_ref (WatchFD *watch_fd)
+{
+ watch_fd->refcount += 1;
+}
+
+static void
+watch_fd_unref (WatchFD *watch_fd)
+{
+ watch_fd->refcount -= 1;
+
+ if (watch_fd->refcount == 0)
+ {
+ g_assert (watch_fd->removed);
+
+ g_free (watch_fd);
+ }
+}
+
static dbus_int32_t connection_slot = -1;
static dbus_int32_t server_slot = -1;
@@ -116,13 +155,13 @@ dbus_gsource_check (GSource *source)
DBusGSource *dbus_source = (DBusGSource *)source;
GList *list;
- list = dbus_source->poll_fds;
+ list = dbus_source->watch_fds;
while (list)
{
- GPollFD *poll_fd = list->data;
+ WatchFD *watch_fd = list->data;
- if (poll_fd->revents != 0)
+ if (watch_fd->poll_fd.revents != 0)
return TRUE;
list = list->next;
@@ -152,35 +191,35 @@ dbus_gsource_dispatch (GSource *source,
DBusGSource *dbus_source = (DBusGSource *)source;
GList *copy, *list;
- /* We need to traverse a copy of the list, since it can change in
- dbus_watch_handle(). */
- copy = g_list_copy (dbus_source->poll_fds);
-
+ /* Make a copy of the list and ref all WatchFDs */
+ copy = g_list_copy (dbus_source->watch_fds);
+ g_list_foreach (copy, (GFunc)watch_fd_ref, NULL);
+
list = copy;
while (list)
{
- GPollFD *poll_fd = list->data;
+ WatchFD *watch_fd = list->data;
- if (poll_fd->revents != 0)
+ if (!watch_fd->removed && watch_fd->poll_fd.revents != 0)
{
- DBusWatch *watch = g_hash_table_lookup (dbus_source->watches, poll_fd);
guint condition = 0;
- if (poll_fd->revents & G_IO_IN)
+ if (watch_fd->poll_fd.revents & G_IO_IN)
condition |= DBUS_WATCH_READABLE;
- if (poll_fd->revents & G_IO_OUT)
+ if (watch_fd->poll_fd.revents & G_IO_OUT)
condition |= DBUS_WATCH_WRITABLE;
- if (poll_fd->revents & G_IO_ERR)
+ if (watch_fd->poll_fd.revents & G_IO_ERR)
condition |= DBUS_WATCH_ERROR;
- if (poll_fd->revents & G_IO_HUP)
+ if (watch_fd->poll_fd.revents & G_IO_HUP)
condition |= DBUS_WATCH_HANGUP;
- dbus_watch_handle (watch, condition);
+ dbus_watch_handle (watch_fd->watch, condition);
}
list = list->next;
}
+ g_list_foreach (copy, (GFunc)watch_fd_unref, NULL);
g_list_free (copy);
return TRUE;
@@ -230,7 +269,7 @@ static dbus_bool_t
add_watch (DBusWatch *watch,
gpointer data)
{
- GPollFD *poll_fd;
+ WatchFD *watch_fd;
DBusGSource *dbus_source;
guint flags;
@@ -238,23 +277,24 @@ add_watch (DBusWatch *watch,
return TRUE;
dbus_source = data;
-
- poll_fd = g_new (GPollFD, 1);
- poll_fd->fd = dbus_watch_get_fd (watch);
- poll_fd->events = 0;
+
+ watch_fd = watch_fd_new ();
+ watch_fd->poll_fd.fd = dbus_watch_get_fd (watch);
+ watch_fd->poll_fd.events = 0;
flags = dbus_watch_get_flags (watch);
- dbus_watch_set_data (watch, poll_fd, NULL);
+ dbus_watch_set_data (watch, watch_fd, (DBusFreeFunction)watch_fd_unref);
if (flags & DBUS_WATCH_READABLE)
- poll_fd->events |= G_IO_IN;
+ watch_fd->poll_fd.events |= G_IO_IN;
if (flags & DBUS_WATCH_WRITABLE)
- poll_fd->events |= G_IO_OUT;
- poll_fd->events |= G_IO_ERR | G_IO_HUP;
+ watch_fd->poll_fd.events |= G_IO_OUT;
+ watch_fd->poll_fd.events |= G_IO_ERR | G_IO_HUP;
- g_source_add_poll ((GSource *)dbus_source, poll_fd);
+ watch_fd->watch = watch;
+
+ g_source_add_poll ((GSource *)dbus_source, &watch_fd->poll_fd);
- dbus_source->poll_fds = g_list_prepend (dbus_source->poll_fds, poll_fd);
- g_hash_table_insert (dbus_source->watches, poll_fd, watch);
+ dbus_source->watch_fds = g_list_prepend (dbus_source->watch_fds, watch_fd);
return TRUE;
}
@@ -264,21 +304,22 @@ remove_watch (DBusWatch *watch,
gpointer data)
{
DBusGSource *dbus_source = data;
- GPollFD *poll_fd;
+ WatchFD *watch_fd;
- poll_fd = dbus_watch_get_data (watch);
- if (poll_fd == NULL)
+ watch_fd = dbus_watch_get_data (watch);
+ if (watch_fd == NULL)
return; /* probably a not-enabled watch that was added */
+
+ watch_fd->removed = TRUE;
+ watch_fd->watch = NULL;
- dbus_source->poll_fds = g_list_remove (dbus_source->poll_fds, poll_fd);
- g_hash_table_remove (dbus_source->watches, poll_fd);
- g_source_remove_poll ((GSource *)dbus_source, poll_fd);
+ dbus_source->watch_fds = g_list_remove (dbus_source->watch_fds, watch_fd);
+
+ g_source_remove_poll ((GSource *)dbus_source, &watch_fd->poll_fd);
dbus_watch_set_data (watch, NULL, NULL); /* needed due to watch_toggled
* breaking add/remove symmetry
*/
-
- g_free (poll_fd);
}
static void
@@ -382,7 +423,6 @@ create_source (void *connection_or_server,
source = g_source_new (funcs, sizeof (DBusGSource));
dbus_source = (DBusGSource *)source;
- dbus_source->watches = g_hash_table_new (NULL, NULL);
dbus_source->connection_or_server = connection_or_server;
dbus_source->context = context;