From d51fe5319381c1f9f6e482f2e4afea38d3816153 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 3 May 2009 01:32:40 +0300 Subject: [PATCH] obexd: Fix DBusPendingCall and GIOChannel tracking There were several issues regarding DBusPendingCall and GIOChannel reference counting and tracking after the transition to BtIO. This patch should (hopefully) fix these issues. --- obexd/src/bluetooth.c | 1 - obexd/src/main.c | 16 +++++++--- obexd/src/manager.c | 70 ++++++++++++++++++++++++++----------------- obexd/src/obex.c | 11 ++++--- obexd/src/obex.h | 2 +- 5 files changed, 61 insertions(+), 39 deletions(-) diff --git a/obexd/src/bluetooth.c b/obexd/src/bluetooth.c index 990a10836..5c43d2b4a 100644 --- a/obexd/src/bluetooth.c +++ b/obexd/src/bluetooth.c @@ -72,7 +72,6 @@ static void confirm_event(GIOChannel *io, gpointer user_data) } info("New connection from: %s, channel %u", address, channel); - g_io_channel_set_close_on_unref(io, FALSE); if (server->services != OBEX_OPP) { if (request_service_authorization(server, io, address) < 0) diff --git a/obexd/src/main.c b/obexd/src/main.c index f6fac74cc..84f318e7e 100644 --- a/obexd/src/main.c +++ b/obexd/src/main.c @@ -75,6 +75,7 @@ int tty_init(int services, const gchar *root_path, struct termios options; int fd, err, arg; glong flags; + GIOChannel *io = NULL; tty_needs_reinit = TRUE; @@ -113,12 +114,18 @@ int tty_init(int services, const gchar *root_path, server->rx_mtu = TTY_RX_MTU; server->tx_mtu = TTY_TX_MTU; - err = obex_session_start(fd, server); + io = g_io_channel_unix_new(fd); + g_io_channel_set_close_on_unref(io, TRUE); + + err = obex_session_start(io, server); + g_io_channel_unref(io); + if (err < 0) { server_free(server); goto failed; - } else - tty_needs_reinit = FALSE; + } + + tty_needs_reinit = FALSE; debug("Successfully opened %s", devnode); @@ -126,7 +133,8 @@ int tty_init(int services, const gchar *root_path, failed: error("tty_init(): %s (%d)", strerror(-err), -err); - close(fd); + if (io == NULL) + close(fd); return err; } diff --git a/obexd/src/manager.c b/obexd/src/manager.c index 90f266392..0514b10b0 100644 --- a/obexd/src/manager.c +++ b/obexd/src/manager.c @@ -232,6 +232,7 @@ struct agent { static struct agent *agent = NULL; struct pending_request { + DBusPendingCall *call; struct server *server; gchar *adapter_path; char address[18]; @@ -641,7 +642,7 @@ done: dbus_message_unref(reply); } -static void find_adapter(const char *pattern, +static DBusPendingCall *find_adapter(const char *pattern, DBusPendingCallNotifyFunction function, gpointer user_data) { @@ -658,21 +659,29 @@ static void find_adapter(const char *pattern, dbus_connection_send_with_reply(system_conn, msg, &call, -1); dbus_pending_call_set_notify(call, function, user_data, NULL); - dbus_pending_call_unref(call); dbus_message_unref(msg); + + return call; } -static gboolean find_adapter_any(gpointer user_data) +static gboolean find_adapter_any_idle(gpointer user_data) { - find_adapter("any", find_adapter_any_reply, user_data); + DBusPendingCall *call; + + call = find_adapter("any", find_adapter_any_reply, NULL); + dbus_pending_call_unref(call); return FALSE; } static void name_acquired(DBusConnection *conn, void *user_data) { - find_adapter_any(NULL); + DBusPendingCall *call; + + call = find_adapter("any", find_adapter_any_reply, NULL); + dbus_pending_call_unref(call); + bluetooth_start(); } @@ -710,7 +719,7 @@ gboolean manager_init(void) listener_id = g_dbus_add_service_watch(system_conn, "org.bluez", name_acquired, name_released, NULL, NULL); - g_idle_add(find_adapter_any, NULL); + g_idle_add(find_adapter_any_idle, NULL); return g_dbus_register_interface(connection, OPENOBEX_MANAGER_PATH, OPENOBEX_MANAGER_INTERFACE, @@ -1002,19 +1011,26 @@ static void service_cancel(struct pending_request *pending) void obex_connect_cb(GIOChannel *io, GError *err, gpointer user_data) { struct server *server = user_data; - gint sk; if (err) { error("%s", err->message); + g_io_channel_shutdown(io, TRUE, NULL); return; } - sk = g_io_channel_unix_get_fd(io); - - if (obex_session_start(sk, server) < 0) + if (obex_session_start(io, server) < 0) g_io_channel_shutdown(io, TRUE, NULL); } +static void pending_request_free(struct pending_request *pending) +{ + if (pending->call) + dbus_pending_call_unref(pending->call); + g_io_channel_unref(pending->io); + g_free(pending->adapter_path); + g_free(pending); +} + static void service_reply(DBusPendingCall *call, gpointer user_data) { struct pending_request *pending = user_data; @@ -1046,10 +1062,8 @@ static void service_reply(DBusPendingCall *call, gpointer user_data) } done: - if (pending->watch) - g_source_remove(pending->watch); - g_free(pending->adapter_path); - g_free(pending); + g_source_remove(pending->watch); + pending_request_free(pending); dbus_message_unref(reply); } @@ -1058,10 +1072,12 @@ static gboolean service_error(GIOChannel *io, GIOCondition cond, { struct pending_request *pending = user_data; - pending->watch = 0; - service_cancel(pending); + dbus_pending_call_cancel(pending->call); + + pending_request_free(pending); + return FALSE; } @@ -1071,8 +1087,7 @@ static void find_adapter_reply(DBusPendingCall *call, gpointer user_data) DBusMessage *reply = dbus_pending_call_steal_reply(call); DBusMessage *msg; DBusPendingCall *pcall; - const char *paddr = pending->address; - const char *path; + const char *path, *paddr = pending->address; DBusError derr; dbus_error_init(&derr); @@ -1108,24 +1123,25 @@ static void find_adapter_reply(DBusPendingCall *call, gpointer user_data) debug("RequestAuthorization(%s, %x)", paddr, pending->server->handle); - if (!dbus_pending_call_set_notify(pcall, service_reply, pending, NULL)) + if (!dbus_pending_call_set_notify(pcall, service_reply, pending, + NULL)) { + dbus_pending_call_unref(pcall); goto failed; + } - dbus_pending_call_unref(pcall); + dbus_pending_call_unref(pending->call); + pending->call = pcall; /* Catches errors before authorization response comes */ - pending->watch = g_io_add_watch_full(pending->io, G_PRIORITY_DEFAULT, + pending->watch = g_io_add_watch(pending->io, G_IO_HUP | G_IO_ERR | G_IO_NVAL, - service_error, pending, NULL); - g_io_channel_unref(pending->io); + service_error, pending); return; failed: - g_free(pending->adapter_path); g_io_channel_shutdown(pending->io, TRUE, NULL); - g_io_channel_unref(pending->io); - g_free(pending); + pending_request_free(pending); } gint request_service_authorization(struct server *server, GIOChannel *io, @@ -1152,7 +1168,7 @@ gint request_service_authorization(struct server *server, GIOChannel *io, pending->io = g_io_channel_ref(io); memcpy(pending->address, address, sizeof(pending->address)); - find_adapter(source, find_adapter_reply, pending); + pending->call = find_adapter(source, find_adapter_reply, pending); return 0; } diff --git a/obexd/src/obex.c b/obexd/src/obex.c index 9dd302f25..490b537d8 100644 --- a/obexd/src/obex.c +++ b/obexd/src/obex.c @@ -978,12 +978,11 @@ failed: return FALSE; } -gint obex_session_start(gint fd, struct server *server) +gint obex_session_start(GIOChannel *io, struct server *server) { struct obex_session *os; - GIOChannel *io; obex_t *obex; - gint ret; + gint ret, fd; os = g_new0(struct obex_session, 1); @@ -1010,6 +1009,8 @@ gint obex_session_start(gint fd, struct server *server) OBEX_SetTransportMTU(obex, os->rx_mtu, os->tx_mtu); + fd = g_io_channel_unix_get_fd(io); + ret = FdOBEX_TransportSetup(obex, fd, fd, 0); if (ret < 0) { obex_session_free(os); @@ -1017,12 +1018,10 @@ gint obex_session_start(gint fd, struct server *server) return ret; } - io = g_io_channel_unix_new(fd); g_io_add_watch_full(io, G_PRIORITY_DEFAULT, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, obex_handle_input, obex, obex_handle_destroy); - g_io_channel_set_close_on_unref(io, TRUE); - os->io = io; + os->io = g_io_channel_ref(io); sessions = g_slist_prepend(sessions, os); diff --git a/obexd/src/obex.h b/obexd/src/obex.h index 49f8b25f9..2f3659715 100644 --- a/obexd/src/obex.h +++ b/obexd/src/obex.h @@ -88,7 +88,7 @@ struct obex_session { gboolean finished; }; -gint obex_session_start(gint fd, struct server *server); +gint obex_session_start(GIOChannel *io, struct server *server); gint obex_tty_session_stop(void); void opp_get(obex_t *obex, obex_object_t *obj); -- 2.47.3