Eo legacy events: Fix broken callback comparison

Commit 37f84b7e96 introduced a few changes
to the callback matching mechanism that made it so sometimes callbacks
would be triggered for the wrong events. The problem was there because
of the support for legacy events that forces to do string comparison
instead of the usual pointer comparison. We should only do string
comparison when we are certain one of the callbacks is a legacy
generated one.

Regression tests will follow tomorrow. Way too late here for that.

Thanks to cedric for reporting.
This commit is contained in:
Tom Hacohen 2015-09-29 00:45:34 +01:00
parent e2344b9b9e
commit d889da6b12
3 changed files with 39 additions and 6 deletions

View File

@ -919,6 +919,8 @@ typedef void (*eo_key_data_free_func)(void *);
/**
* Don't use.
* The values of the returned event structure are also internal, don't assume
* anything about them.
* @internal
*/
EAPI const Eo_Event_Description *eo_base_legacy_only_event_description_get(const char *_event_name);

View File

@ -401,11 +401,16 @@ _wref_destruct(Eo_Base_Data *pd)
/* XXX: Legacy support, remove when legacy is dead. */
static Eina_Hash *_legacy_events_hash = NULL;
#define _LEGACY_EVENT_FIRST_CHAR 1
EAPI const Eo_Event_Description *
eo_base_legacy_only_event_description_get(const char *_event_name)
{
Eina_Stringshare *event_name = eina_stringshare_add(_event_name);
char buf[1024];
buf[0] = _LEGACY_EVENT_FIRST_CHAR; /* Encode it's a legacy event */
strncpy(buf + 1, _event_name, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
Eina_Stringshare *event_name = eina_stringshare_add(buf);
Eo_Event_Description *event_desc = eina_hash_find(_legacy_events_hash, event_name);
if (!event_desc)
{
@ -421,6 +426,26 @@ eo_base_legacy_only_event_description_get(const char *_event_name)
return event_desc;
}
static Eina_Bool
_legacy_event_desc_is(const Eo_Event_Description *desc)
{
return (desc->name[0] == _LEGACY_EVENT_FIRST_CHAR);
}
/* Also supports non legacy. */
static const char *
_legacy_event_desc_name_get(const Eo_Event_Description *desc)
{
if (_legacy_event_desc_is(desc))
{
return desc->name + 1;
}
else
{
return desc->name;
}
}
static void
_legacy_events_hash_free_cb(void *_desc)
{
@ -641,13 +666,19 @@ _cb_desc_match(const Eo_Event_Description *a, const Eo_Event_Description *b)
if (!a)
return EINA_FALSE;
if (a == b)
if (_legacy_event_desc_is(a) && _legacy_event_desc_is(b))
{
return EINA_TRUE;
return (a->name == b->name);
}
else if (_legacy_event_desc_is(a) || _legacy_event_desc_is(b))
{
const char *aname = _legacy_event_desc_name_get(a);
const char *bname = _legacy_event_desc_name_get(b);
return !strcmp(aname, bname);
}
else
{
return !strcmp(a->name, b->name);
return (a == b);
}
}

View File

@ -125,12 +125,12 @@ START_TEST(eo_signals)
{
const Eo_Event_Description *a_desc = eo_base_legacy_only_event_description_get("a,changed");
fail_if(!a_desc);
ck_assert_str_eq(a_desc->name, "a,changed");
ck_assert_str_eq(a_desc->name, "\x01" "a,changed");
fail_if(a_desc == EV_A_CHANGED);
const Eo_Event_Description *bad_desc = eo_base_legacy_only_event_description_get("bad");
fail_if(!bad_desc);
ck_assert_str_eq(bad_desc->name, "bad");
ck_assert_str_eq(bad_desc->name, "\x01" "bad");
/* Call Eo event with legacy and non-legacy callbacks. */
_eo_signals_cb_current = 0;