eina: Fix promise error with eina_promise_all

Fix value_set and error_set signatures which were receiving a
owner. They actually receive the promise and not the owner, this
caused wrong access to memory and were not visible by warnings because
the functions are casted.

This problem caused errors in which it seemed that promise had
actually error'ed when questioned it.
This commit is contained in:
Felipe Magno de Almeida 2016-04-13 14:43:43 -03:00
parent acc1a5dcc0
commit 35dd5b5cab
2 changed files with 73 additions and 16 deletions

View File

@ -108,7 +108,6 @@ _eina_promise_then_calls(_Eina_Promise_Default_Owner* promise)
}
else if (callback->callback)
{
fprintf(stderr, "then callback\n");
(*callback->callback)(callback->data, &promise->value[0]);
}
_eina_promise_unref(&promise->promise);
@ -151,18 +150,18 @@ _eina_promise_del(_Eina_Promise_Default_Owner* promise)
}
static void *
_eina_promise_buffer_get(_Eina_Promise_Default_Owner* promise)
_eina_promise_owner_buffer_get(_Eina_Promise_Default_Owner* promise)
{
return &promise->value[0];
}
static void *
_eina_promise_value_get(_Eina_Promise_Default_Owner const* promise)
_eina_promise_value_get(_Eina_Promise_Default const* p)
{
if (promise->promise.has_finished)
_Eina_Promise_Default_Owner const* promise = EINA_PROMISE_GET_OWNER(p);
if (promise->promise.has_finished && !promise->promise.has_errored)
{
return (void*)(promise->promise.value_size && !promise->promise.has_errored ?
&promise->value[0] : NULL);
return (void*)&promise->value[0];
}
else
{
@ -171,7 +170,7 @@ _eina_promise_value_get(_Eina_Promise_Default_Owner const* promise)
}
static void
_eina_promise_value_set(_Eina_Promise_Default_Owner* promise, void* data, Eina_Promise_Free_Cb free)
_eina_promise_owner_value_set(_Eina_Promise_Default_Owner* promise, void* data, Eina_Promise_Free_Cb free)
{
if (data && promise->promise.value_size)
{
@ -198,7 +197,6 @@ _eina_promise_then(_Eina_Promise_Default* p, Eina_Promise_Cb callback,
cb->error_cb = error_cb;
cb->data = data;
promise->promise.then_callbacks = eina_inlist_append(promise->promise.then_callbacks, EINA_INLIST_GET(cb));
fprintf(stderr, "appending then callback\n");
if (!promise->promise.is_first_then)
{
@ -212,7 +210,7 @@ _eina_promise_then(_Eina_Promise_Default* p, Eina_Promise_Cb callback,
}
static void
_eina_promise_error_set(_Eina_Promise_Default_Owner* promise, Eina_Error error)
_eina_promise_owner_error_set(_Eina_Promise_Default_Owner* promise, Eina_Error error)
{
promise->promise.error = error;
promise->promise.has_errored = EINA_TRUE;
@ -231,11 +229,11 @@ _eina_promise_finish(_Eina_Promise_Default_Owner* promise)
}
static Eina_Error
_eina_promise_error_get(_Eina_Promise_Default_Owner const* promise)
_eina_promise_error_get(_Eina_Promise_Default const* promise)
{
if (promise->promise.has_errored)
if (promise->has_errored)
{
return promise->promise.error;
return promise->error;
}
else
{
@ -292,6 +290,12 @@ _eina_promise_value_size_get(_Eina_Promise_Default_Owner const* promise)
return promise->promise.value_size;
}
static size_t
_eina_promise_owner_value_size_get(_Eina_Promise_Default_Owner const* promise)
{
return promise->promise.value_size;
}
static void
_eina_promise_ref(_Eina_Promise_Default* p)
{
@ -377,12 +381,13 @@ eina_promise_default_add(int value_size)
memset(&p->promise.cancel_callbacks, 0, sizeof(p->promise.cancel_callbacks));
p->promise.value_size = value_size;
p->promise.value_free_cb = NULL;
p->promise.error = 0;
p->owner_vtable.version = EINA_PROMISE_VERSION;
p->owner_vtable.value_set = EINA_FUNC_PROMISE_OWNER_VALUE_SET(_eina_promise_value_set);
p->owner_vtable.error_set = EINA_FUNC_PROMISE_OWNER_ERROR_SET(_eina_promise_error_set);
p->owner_vtable.buffer_get = EINA_FUNC_PROMISE_OWNER_BUFFER_GET(_eina_promise_buffer_get);
p->owner_vtable.value_size_get = EINA_FUNC_PROMISE_OWNER_VALUE_SIZE_GET(_eina_promise_value_size_get);
p->owner_vtable.value_set = EINA_FUNC_PROMISE_OWNER_VALUE_SET(_eina_promise_owner_value_set);
p->owner_vtable.error_set = EINA_FUNC_PROMISE_OWNER_ERROR_SET(_eina_promise_owner_error_set);
p->owner_vtable.buffer_get = EINA_FUNC_PROMISE_OWNER_BUFFER_GET(_eina_promise_owner_buffer_get);
p->owner_vtable.value_size_get = EINA_FUNC_PROMISE_OWNER_VALUE_SIZE_GET(_eina_promise_owner_value_size_get);
p->owner_vtable.promise_get = EINA_FUNC_PROMISE_OWNER_PROMISE_GET(_eina_promise_owner_promise_get);
p->owner_vtable.pending_is = EINA_FUNC_PROMISE_OWNER_PENDING_IS(_eina_promise_owner_pending_is);
p->owner_vtable.cancelled_is = EINA_FUNC_PROMISE_OWNER_CANCELLED_IS(_eina_promise_owner_cancelled_is);

View File

@ -122,6 +122,57 @@ START_TEST(eina_test_promise_immediate_set_lifetime_all)
}
END_TEST
static void _eina_test_promise_value_all_cb(void* data, void* value)
{
Eina_Iterator** iterator = value;
int *i, *j;
Eina_Bool b;
b = eina_iterator_next(*iterator, (void**)&i);
ck_assert(!!b);
b = eina_iterator_next(*iterator, (void**)&j);
ck_assert(!!b);
ck_assert(i != NULL);
ck_assert(j != NULL);
ck_assert(*i == 10);
ck_assert(*j == 15);
*(Eina_Bool*)data = EINA_TRUE;
}
START_TEST(eina_test_promise_values_all)
{
Eina_Promise_Owner* owners[2];
Eina_Promise* promises[3] = {NULL, NULL, NULL};
Eina_Promise* promise_all;
Eina_Bool ran = EINA_FALSE;
eina_init();
int i = 10, j = 15;
owners[0] = eina_promise_default_add(sizeof(int));
owners[1] = eina_promise_default_add(sizeof(int));
promises[0] = eina_promise_owner_promise_get(owners[0]);
promises[1] = eina_promise_owner_promise_get(owners[1]);
promise_all = eina_promise_all(eina_carray_iterator_new((void**)&promises[0]));
eina_promise_owner_value_set(owners[0], &i, NULL);
eina_promise_owner_value_set(owners[1], &j, NULL);
eina_promise_then(promise_all, &_eina_test_promise_value_all_cb, NULL, &ran);
ck_assert(ran == EINA_TRUE);
eina_shutdown();
}
END_TEST
static void cancel_callback(void* data, Eina_Promise_Owner* promise EINA_UNUSED)
{
*(Eina_Bool*)data = EINA_TRUE;
@ -192,6 +243,7 @@ eina_test_promise(TCase *tc)
tcase_add_test(tc, eina_test_promise_normal_lifetime_all);
tcase_add_test(tc, eina_test_promise_immediate_set_lifetime);
tcase_add_test(tc, eina_test_promise_immediate_set_lifetime_all);
tcase_add_test(tc, eina_test_promise_values_all);
tcase_add_test(tc, eina_test_promise_cancel_promise);
tcase_add_test(tc, eina_test_promise_progress);
}