summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGustavo Sverzut Barbieri <barbieri@profusion.mobi>2017-08-27 00:27:40 -0300
committerGustavo Sverzut Barbieri <barbieri@profusion.mobi>2017-08-27 11:35:38 -0300
commit07f272b52ed26802db544d82194df4a13ad2ee64 (patch)
treee1cefbf24280548d7a6091a400f018aeffd853b6
parentc35e929713da501d9e9323613f8708436dbc596b (diff)
fixup Eina: Add Eina_Promise/Eina_Future
_eina_promise_clean_dispatch() must call _eina_future_dispatch() since complex chains will need to be walked -- this bugged me for some complex tests I'm doing with coroutines. Unfortunately that will modify the value and cause problems since the caller trust it wasn't modified and could cause double-free or invalid memory access. Then we must copy it in _future_proxy(). Other usage for _eina_promise_clean_dispatch() were leaking and are now "auto fixed".
-rw-r--r--src/lib/eina/eina_promise.c23
1 files changed, 17 insertions, 6 deletions
diff --git a/src/lib/eina/eina_promise.c b/src/lib/eina/eina_promise.c
index 6f55414739..1eb319437f 100644
--- a/src/lib/eina/eina_promise.c
+++ b/src/lib/eina/eina_promise.c
@@ -363,7 +363,11 @@ _eina_future_dispatch_internal(Eina_Future **f,
363 363
364 assert(value.type != &EINA_VALUE_TYPE_PROMISE2); 364 assert(value.type != &EINA_VALUE_TYPE_PROMISE2);
365 while ((*f) && (!(*f)->cb)) *f = _eina_future_free(*f); 365 while ((*f) && (!(*f)->cb)) *f = _eina_future_free(*f);
366 if (!*f) return value; 366 if (!*f)
367 {
368 _eina_promise_value_dbg("No future to deliver value", NULL, value);
369 return value;
370 }
367 next_value = _eina_future_cb_dispatch(*f, value); 371 next_value = _eina_future_cb_dispatch(*f, value);
368 *f = _eina_future_free(*f); 372 *f = _eina_future_free(*f);
369 return next_value; 373 return next_value;
@@ -576,17 +580,15 @@ eina_promise_as_value(Eina_Promise *p)
576} 580}
577 581
578static void 582static void
579_eina_promise_clean_dispatch(Eina_Promise *p, const Eina_Value v) 583_eina_promise_clean_dispatch(Eina_Promise *p, Eina_Value v)
580{ 584{
581 Eina_Value r;
582 Eina_Future *f = p->future; 585 Eina_Future *f = p->future;
583 586
584 if (f) 587 if (f)
585 { 588 {
586 _eina_promise_value_dbg("Clean contenxt - Resolving promise", p, v); 589 _eina_promise_value_dbg("Clean contenxt - Resolving promise", p, v);
587 _eina_promise_unlink(p); 590 _eina_promise_unlink(p);
588 r = _eina_future_dispatch_internal(&f, v); 591 _eina_future_dispatch(f, v);
589 if (!_eina_value_is(v, r)) _eina_value_safe_flush(r);
590 } 592 }
591 eina_mempool_free(_promise_mp, p); 593 eina_mempool_free(_promise_mp, p);
592} 594}
@@ -595,8 +597,16 @@ static Eina_Value
595_future_proxy(void *data, const Eina_Value v, 597_future_proxy(void *data, const Eina_Value v,
596 const Eina_Future *dead_future EINA_UNUSED) 598 const Eina_Future *dead_future EINA_UNUSED)
597{ 599{
600 Eina_Value copy;
598 //We're in a safe context (from mainloop), so we can avoid scheduling a new dispatch 601 //We're in a safe context (from mainloop), so we can avoid scheduling a new dispatch
599 _eina_promise_clean_dispatch(data, v); 602 if (!v.type) copy = v;
603 else if (!eina_value_copy(&v, &copy))
604 {
605 ERR("Value cannot be copied - unusable with Eina_Future: %p (%s)", v.type, v.type->name);
606 eina_value_setup(&copy, EINA_VALUE_TYPE_ERROR);
607 eina_value_set(&copy, ENOTSUP);
608 }
609 _eina_promise_clean_dispatch(data, copy);
600 return v; 610 return v;
601} 611}
602 612
@@ -1110,6 +1120,7 @@ _all_then_cb(void *data, const Eina_Value v,
1110 { 1120 {
1111 //We're in a safe context (from mainloop), so we can avoid scheduling a new dispatch 1121 //We're in a safe context (from mainloop), so we can avoid scheduling a new dispatch
1112 _eina_promise_clean_dispatch(ctx->base.promise, ctx->values); 1122 _eina_promise_clean_dispatch(ctx->base.promise, ctx->values);
1123 ctx->values = EINA_VALUE_EMPTY; /* flushed in _eina_promise_clean_dispatch() */
1113 _all_promise2_ctx_free(ctx); 1124 _all_promise2_ctx_free(ctx);
1114 } 1125 }
1115 return v; 1126 return v;