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 <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2016-06-09 00:03:08 +02:00 committed by Daniel Hahler
parent 2d511e2ab5
commit 6f1df7a3ad
5 changed files with 11 additions and 10 deletions

View File

@ -278,8 +278,8 @@ luaA_class_disconnect_signal_from_stack(lua_State *L, lua_class_t *lua_class,
{ {
luaA_checkfunction(L, ud); luaA_checkfunction(L, ud);
void *ref = (void *) lua_topointer(L, ud); void *ref = (void *) lua_topointer(L, ud);
signal_disconnect(&lua_class->signals, name, ref); if (signal_disconnect(&lua_class->signals, name, ref))
luaA_object_unref(L, (void *) ref); luaA_object_unref(L, (void *) ref);
lua_remove(L, ud); lua_remove(L, ud);
} }

View File

@ -222,8 +222,8 @@ luaA_object_disconnect_signal_from_stack(lua_State *L, int oud,
luaA_checkfunction(L, ud); luaA_checkfunction(L, ud);
lua_object_t *obj = lua_touserdata(L, oud); lua_object_t *obj = lua_touserdata(L, oud);
void *ref = (void *) lua_topointer(L, ud); void *ref = (void *) lua_topointer(L, ud);
signal_disconnect(&obj->signals, name, ref); if (signal_disconnect(&obj->signals, name, ref))
luaA_object_unref_item(L, oud, ref); luaA_object_unref_item(L, oud, ref);
lua_remove(L, ud); lua_remove(L, ud);
} }

View File

@ -81,7 +81,7 @@ signal_connect(signal_array_t *arr, const char *name, const void *ref)
* \param name The signal name. * \param name The signal name.
* \param ref The reference to remove. * \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_disconnect(signal_array_t *arr, const char *name, const void *ref)
{ {
signal_t *sigfound = signal_array_getbyid(arr, 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) if(ref == *func)
{ {
cptr_array_remove(&sigfound->sigfuncs, func); cptr_array_remove(&sigfound->sigfuncs, func);
break; return true;
} }
} }
return false;
} }
#endif #endif

4
dbus.c
View File

@ -789,8 +789,8 @@ luaA_dbus_disconnect_signal(lua_State *L)
const char *name = luaL_checkstring(L, 1); const char *name = luaL_checkstring(L, 1);
luaA_checkfunction(L, 2); luaA_checkfunction(L, 2);
const void *func = lua_topointer(L, 2); const void *func = lua_topointer(L, 2);
signal_disconnect(&dbus_signals, name, func); if (signal_disconnect(&dbus_signals, name, func))
luaA_object_unref(L, func); luaA_object_unref(L, func);
return 0; return 0;
} }

4
luaa.c
View File

@ -395,8 +395,8 @@ luaA_awesome_disconnect_signal(lua_State *L)
const char *name = luaL_checkstring(L, 1); const char *name = luaL_checkstring(L, 1);
luaA_checkfunction(L, 2); luaA_checkfunction(L, 2);
const void *func = lua_topointer(L, 2); const void *func = lua_topointer(L, 2);
signal_disconnect(&global_signals, name, func); if (signal_disconnect(&global_signals, name, func))
luaA_object_unref(L, (void *) func); luaA_object_unref(L, (void *) func);
return 0; return 0;
} }