edbus: Fix bug found in refactored banshee example

Refactor edbus_signal_handler_add() so internal signal handlers don't
set the connection free callback. This fixes the bug in which
EDBus_Connection was freeing the signal handler of EDBus_Conenction_Name

==22814== Invalid read of size 4
==22814==    at 0x40564B0: edbus_signal_handler_del (edbus_signal_handler.c:278)
==22814==    by 0x4040E65: _edbus_connection_name_unref (edbus_core.c:507)
==22814==    by 0x404106B: edbus_connection_name_owner_monitor (edbus_core.c:520)
==22814==    by 0x4055F63: _edbus_signal_handler_clean (edbus_signal_handler.c:217)
==22814==    by 0x40564F8: edbus_signal_handler_del (edbus_signal_handler.c:279)
==22814==    by 0x4043088: _edbus_connection_unref (edbus_core.c:1045)
==22814==    by 0x404352F: edbus_connection_unref (edbus_core.c:1105)
==22814==    by 0x80498AA: main (banshee.c:233)
==22814==  Address 0x44bea48 is 0 bytes inside a block of size 72 free'd
==22814==    at 0x402C06C: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==22814==    by 0x4056118: _edbus_signal_handler_del (edbus_signal_handler.c:249)
==22814==    by 0x4056401: edbus_signal_handler_unref (edbus_signal_handler.c:272)
==22814==    by 0x4056503: edbus_signal_handler_del (edbus_signal_handler.c:280)
==22814==    by 0x4043088: _edbus_connection_unref (edbus_core.c:1045)
==22814==    by 0x404352F: edbus_connection_unref (edbus_core.c:1105)
==22814==    by 0x80498AA: main (banshee.c:233)
==22814==
CRI<22814>: src/lib/edbus_signal_handler.c:278 edbus_signal_handler_del() *** Eina Magic Check Failed !!!
    Input handle has already been freed!
    *** NAUGHTY PROGRAMMER!!!
    *** SPANK SPANK SPANK!!!
    *** Now go fix your code. Tut tut tut!

Patch by: José Roberto de Souza  <zehortigoza@profusion.mobi>



SVN revision: 80686
This commit is contained in:
José Roberto de Souza 2012-12-11 19:50:01 +00:00 committed by Lucas De Marchi
parent bafc3adf76
commit 00e6dac1ac
5 changed files with 56 additions and 26 deletions

View File

@ -499,11 +499,11 @@ edbus_connection_name_get(EDBus_Connection *conn, const char *name)
goto end;
}
edbus_name_owner_get(conn, cn->name, on_get_name_owner, cn);
cn->name_owner_changed = edbus_signal_handler_add(conn, EDBUS_FDO_BUS,
EDBUS_FDO_PATH,
EDBUS_FDO_INTERFACE,
"NameOwnerChanged",
on_name_owner_changed, cn);
cn->name_owner_changed = _edbus_signal_handler_add(conn, EDBUS_FDO_BUS,
EDBUS_FDO_PATH,
EDBUS_FDO_INTERFACE,
"NameOwnerChanged",
on_name_owner_changed, cn);
edbus_signal_handler_match_extra_set(cn->name_owner_changed, "arg0",
cn->name, NULL);
@ -1000,13 +1000,6 @@ _edbus_connection_unref(EDBus_Connection *conn)
EINA_INLIST_FOREACH_SAFE(conn->pendings, list, p)
edbus_pending_cancel(p);
while (conn->signal_handlers)
{
list = conn->signal_handlers;
h = EINA_INLIST_CONTAINER_GET(conn->signal_handlers, EDBus_Signal_Handler);
edbus_signal_handler_del(h);
}
iter = eina_hash_iterator_data_new(conn->names);
EINA_ITERATOR_FOREACH(iter, cn)
{
@ -1033,14 +1026,21 @@ _edbus_connection_unref(EDBus_Connection *conn)
CRITICAL("Connection %p released with live pending calls!",
conn);
EINA_INLIST_FOREACH(conn->pendings, p)
ERR("conn=%p alive pending call=%p dest=%s path=%s %s.%s()",
conn, p,
ERR("conn=%p alive pending call=%p dest=%s path=%s %s.%s()", conn, p,
edbus_pending_destination_get(p),
edbus_pending_path_get(p),
edbus_pending_interface_get(p),
edbus_pending_method_get(p));
}
if (conn->signal_handlers)
{
CRITICAL("Connection %p released with live signal handlers!", conn);
EINA_INLIST_FOREACH(conn->signal_handlers, h)
ERR("conn=%p alive signal=%p %s.%s path=%s", conn, h, h->interface,
h->member, h->path);
}
for (i = 0; i < EDBUS_CONNECTION_EVENT_LAST; i++)
{
EDBus_Connection_Context_Event *ce = conn->event_handlers + i;

View File

@ -399,10 +399,10 @@ edbus_object_event_callback_add(EDBus_Object *obj, EDBus_Object_Event_Type type,
if (obj->interfaces_added)
break;
obj->interfaces_added =
edbus_signal_handler_add(obj->conn, obj->name, NULL,
EDBUS_FDO_INTERFACE_OBJECT_MANAGER,
"InterfacesAdded",
_cb_interfaces_added, obj);
_edbus_signal_handler_add(obj->conn, obj->name, NULL,
EDBUS_FDO_INTERFACE_OBJECT_MANAGER,
"InterfacesAdded",
_cb_interfaces_added, obj);
EINA_SAFETY_ON_NULL_RETURN(obj->interfaces_added);
edbus_signal_handler_match_extra_set(obj->interfaces_added, "arg0",
obj->path, NULL);
@ -413,10 +413,10 @@ edbus_object_event_callback_add(EDBus_Object *obj, EDBus_Object_Event_Type type,
if (obj->interfaces_removed)
break;
obj->interfaces_removed =
edbus_signal_handler_add(obj->conn, obj->name, NULL,
EDBUS_FDO_INTERFACE_OBJECT_MANAGER,
"InterfacesRemoved",
_cb_interfaces_removed, obj);
_edbus_signal_handler_add(obj->conn, obj->name, NULL,
EDBUS_FDO_INTERFACE_OBJECT_MANAGER,
"InterfacesRemoved",
_cb_interfaces_removed, obj);
EINA_SAFETY_ON_NULL_RETURN(obj->interfaces_added);
edbus_signal_handler_match_extra_set(obj->interfaces_removed,
"arg0", obj->path, NULL);
@ -598,8 +598,8 @@ edbus_object_signal_handler_add(EDBus_Object *obj, const char *interface, const
EDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
handler = edbus_signal_handler_add(obj->conn, obj->name, obj->path,
interface, member, cb, cb_data);
handler = _edbus_signal_handler_add(obj->conn, obj->name, obj->path,
interface, member, cb, cb_data);
EINA_SAFETY_ON_NULL_RETURN_VAL(handler, NULL);
edbus_signal_handler_cb_free_add(handler, _on_signal_handler_free, obj);

View File

@ -77,6 +77,8 @@ Eina_Value *_message_iter_struct_to_eina_value(EDBus_Message_Iter *it
void edbus_connection_name_ref(EDBus_Connection_Name *cn);
void edbus_connection_name_unref(EDBus_Connection *conn, EDBus_Connection_Name *cn);
EDBus_Signal_Handler *_edbus_signal_handler_add(EDBus_Connection *conn, const char *sender, const char *path, const char *interface, const char *member, EDBus_Signal_Cb cb, const void *cb_data);
#ifdef HAVE_VA_LIST_AS_ARRAY
#define MAKE_PTR_FROM_VA_LIST(arg) ((va_list *)(arg))

View File

@ -605,8 +605,8 @@ edbus_proxy_signal_handler_add(EDBus_Proxy *proxy, const char *member, EDBus_Sig
name = edbus_object_bus_name_get(proxy->obj);
path = edbus_object_path_get(proxy->obj);
handler = edbus_signal_handler_add(proxy->obj->conn, name, path,
proxy->interface, member, cb, cb_data);
handler = _edbus_signal_handler_add(proxy->obj->conn, name, path,
proxy->interface, member, cb, cb_data);
EINA_SAFETY_ON_NULL_RETURN_VAL(handler, NULL);
edbus_signal_handler_cb_free_add(handler, _on_signal_handler_free, proxy);

View File

@ -148,8 +148,36 @@ edbus_signal_handler_match_extra_set(EDBus_Signal_Handler *sh, ...)
return ret;
}
static void _on_handler_of_conn_free(void *data, const void *dead_pointer);
static void
_on_connection_free(void *data, const void *dead_pointer)
{
EDBus_Signal_Handler *sh = data;
edbus_signal_handler_cb_free_del(sh, _on_handler_of_conn_free, sh->conn);
edbus_signal_handler_del(sh);
}
static void
_on_handler_of_conn_free(void *data, const void *dead_pointer)
{
EDBus_Connection *conn = data;
edbus_connection_cb_free_del(conn, _on_connection_free, dead_pointer);
}
EAPI EDBus_Signal_Handler *
edbus_signal_handler_add(EDBus_Connection *conn, const char *sender, const char *path, const char *interface, const char *member, EDBus_Signal_Cb cb, const void *cb_data)
{
EDBus_Signal_Handler *sh;
sh = _edbus_signal_handler_add(conn, sender, path, interface, member, cb, cb_data);
EINA_SAFETY_ON_NULL_RETURN_VAL(sh, NULL);
edbus_connection_cb_free_add(conn, _on_connection_free, sh);
edbus_signal_handler_cb_free_add(sh, _on_handler_of_conn_free, conn);
return sh;
}
EDBus_Signal_Handler *
_edbus_signal_handler_add(EDBus_Connection *conn, const char *sender, const char *path, const char *interface, const char *member, EDBus_Signal_Cb cb, const void *cb_data)
{
EDBus_Signal_Handler *sh;
Eina_Strbuf *match;