From fbcee7bc9d548612ca8f37db36bab09cd5347038 Mon Sep 17 00:00:00 2001 From: Chengwei Yang Date: Tue, 3 Dec 2013 20:47:54 +0800 Subject: [PATCH v3] Fix memory leak for kqueue: shutdown kqueue correctly There are memory blocks leak when doing bus-test, both dispatch-sha1 and dispatch test cases complain memory blocks leak. This patch also fix fd leaks. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=69332 --- bus/dir-watch-kqueue.c | 87 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 74 insertions(+), 13 deletions(-) diff --git a/bus/dir-watch-kqueue.c b/bus/dir-watch-kqueue.c index 065fabb..4cc780d 100644 --- a/bus/dir-watch-kqueue.c +++ b/bus/dir-watch-kqueue.c @@ -87,11 +87,49 @@ _handle_kqueue_watch (DBusWatch *watch, unsigned int flags, void *data) return TRUE; } +static void _shutdown_kqueue (void *data) +{ + int i; + + if (kq < 0) + return; + + for (i = 0; i < MAX_DIRS_TO_WATCH; i++) + { + if (fds[i] >= 0) + { + close (fds[i]); + fds[i] = -1; + } + if (dirs[i] != NULL) + { + /* dbus_free() is necessary to pass memleak check */ + dbus_free (dirs[i]); + dirs[i] = NULL; + } + } + + if (loop) + { + _dbus_loop_remove_watch (loop, watch); + _dbus_loop_unref (loop); + loop = NULL; + } + + if (watch) + { + _dbus_watch_invalidate (watch); + _dbus_watch_unref (watch); + watch = NULL; + } + + close (kq); + kq = -1; +} + static int _init_kqueue (BusContext *context) { - int ret = 0; - if (kq < 0) { @@ -103,6 +141,7 @@ _init_kqueue (BusContext *context) } loop = bus_context_get_loop (context); + _dbus_loop_ref (loop); watch = _dbus_watch_new (kq, DBUS_WATCH_READABLE, TRUE, _handle_kqueue_watch, NULL, NULL); @@ -110,27 +149,49 @@ _init_kqueue (BusContext *context) if (watch == NULL) { _dbus_warn ("Unable to create kqueue watch\n"); - close (kq); - kq = -1; - goto out; + goto out1; } if (!_dbus_loop_add_watch (loop, watch)) { _dbus_warn ("Unable to add reload watch to main loop"); - _dbus_watch_invalidate (watch); - _dbus_watch_unref (watch); - watch = NULL; - close (kq); - kq = -1; - goto out; + goto out2; + } + + if (!_dbus_register_shutdown_func (_shutdown_kqueue, NULL)) + { + _dbus_warn ("Unable to register shutdown function"); + goto out3; } } - ret = 1; + return 1; + +out3: + _dbus_loop_remove_watch (loop, watch); + +out2: + if (watch) + { + _dbus_watch_invalidate (watch); + _dbus_watch_unref (watch); + watch = NULL; + } + +out1: + if (kq >= 0) + { + close (kq); + kq = -1; + } + if (loop) + { + _dbus_loop_unref (loop); + loop = NULL; + } out: - return ret; + return 0; } void -- 1.7.9.5