From 6f1df7a3ad825e0079ff23ccdf3edfbc1cff1c61 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Thu, 9 Jun 2016 00:03:08 +0200 Subject: [PATCH] Fix disconnecting not connected signals (#950) When a function is disconnected from a signal ("disconnect_signal") that is not actually connected to the function, two things happened: 1. The attempt to remove the function from the signal array didn't do anything 2. Unreferencing the function noticed that the function wasn't referenced The second step printed a big, fat scary warning. Actually, this has the possibility of causing errors. For example, in the following code, awesome would wrongly unreference the function at the disconnect_signal() call and might later still try to call it when the "refresh" signal is emitted: do local function f() end awesome.connect_signal("refresh", f) awesome.disconnect_signal("debug::error", f) end Fix this by making signal_disconnect() return a boolean value indicating if it actually did something. All callers are fixed to use this value and only update the reference counts if something was actually disconnected. Fixes: https://github.com/awesomeWM/awesome/issues/814 Signed-off-by: Uli Schlachter --- common/luaclass.c | 4 ++-- common/luaobject.c | 4 ++-- common/signal.h | 5 +++-- dbus.c | 4 ++-- luaa.c | 4 ++-- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/common/luaclass.c b/common/luaclass.c index f5a40c296..1771aaa2f 100644 --- a/common/luaclass.c +++ b/common/luaclass.c @@ -278,8 +278,8 @@ luaA_class_disconnect_signal_from_stack(lua_State *L, lua_class_t *lua_class, { luaA_checkfunction(L, ud); void *ref = (void *) lua_topointer(L, ud); - signal_disconnect(&lua_class->signals, name, ref); - luaA_object_unref(L, (void *) ref); + if (signal_disconnect(&lua_class->signals, name, ref)) + luaA_object_unref(L, (void *) ref); lua_remove(L, ud); } diff --git a/common/luaobject.c b/common/luaobject.c index 8f55ed0a6..acd4bdee4 100644 --- a/common/luaobject.c +++ b/common/luaobject.c @@ -222,8 +222,8 @@ luaA_object_disconnect_signal_from_stack(lua_State *L, int oud, luaA_checkfunction(L, ud); lua_object_t *obj = lua_touserdata(L, oud); void *ref = (void *) lua_topointer(L, ud); - signal_disconnect(&obj->signals, name, ref); - luaA_object_unref_item(L, oud, ref); + if (signal_disconnect(&obj->signals, name, ref)) + luaA_object_unref_item(L, oud, ref); lua_remove(L, ud); } diff --git a/common/signal.h b/common/signal.h index f2b158394..d9d5e4569 100644 --- a/common/signal.h +++ b/common/signal.h @@ -81,7 +81,7 @@ signal_connect(signal_array_t *arr, const char *name, const void *ref) * \param name The signal name. * \param ref The reference to remove. */ -static inline void +static inline bool signal_disconnect(signal_array_t *arr, const char *name, const void *ref) { signal_t *sigfound = signal_array_getbyid(arr, @@ -92,9 +92,10 @@ signal_disconnect(signal_array_t *arr, const char *name, const void *ref) if(ref == *func) { cptr_array_remove(&sigfound->sigfuncs, func); - break; + return true; } } + return false; } #endif diff --git a/dbus.c b/dbus.c index 4e796139c..dc5bcaffb 100644 --- a/dbus.c +++ b/dbus.c @@ -789,8 +789,8 @@ luaA_dbus_disconnect_signal(lua_State *L) const char *name = luaL_checkstring(L, 1); luaA_checkfunction(L, 2); const void *func = lua_topointer(L, 2); - signal_disconnect(&dbus_signals, name, func); - luaA_object_unref(L, func); + if (signal_disconnect(&dbus_signals, name, func)) + luaA_object_unref(L, func); return 0; } diff --git a/luaa.c b/luaa.c index 37ef6e813..2143f39d1 100644 --- a/luaa.c +++ b/luaa.c @@ -395,8 +395,8 @@ luaA_awesome_disconnect_signal(lua_State *L) const char *name = luaL_checkstring(L, 1); luaA_checkfunction(L, 2); const void *func = lua_topointer(L, 2); - signal_disconnect(&global_signals, name, func); - luaA_object_unref(L, (void *) func); + if (signal_disconnect(&global_signals, name, func)) + luaA_object_unref(L, (void *) func); return 0; }