discomfitor pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=bea602f258092f109b9dc55190358909f58bddfb
commit bea602f258092f109b9dc55190358909f58bddfb Author: Mike Blumenkrantz <[email protected]> Date: Fri Jun 22 15:49:34 2018 -0400 evas/thread_render: improve thread safety this resolves some invalid read/write operations between threads without locking and also attempts to improve thread-related behavior after fork() calls ref T7027 Differential Revision: https://phab.enlightenment.org/D6370 --- src/lib/evas/common/evas_thread_render.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/lib/evas/common/evas_thread_render.c b/src/lib/evas/common/evas_thread_render.c index c823125f69..a4db5f22c7 100644 --- a/src/lib/evas/common/evas_thread_render.c +++ b/src/lib/evas/common/evas_thread_render.c @@ -11,7 +11,8 @@ static Eina_Inarray evas_thread_queue; static Evas_Thread_Command *evas_thread_queue_cache = NULL; static unsigned int evas_thread_queue_cache_max = 0; -static volatile int evas_thread_exited = 0; +static Eina_Lock evas_thread_exited_lock; +static int evas_thread_exited = 0; static Eina_Bool exit_thread = EINA_FALSE; static int init_count = 0; @@ -132,7 +133,7 @@ evas_thread_worker_func(void *data EINA_UNUSED, Eina_Thread thread EINA_UNUSED) eina_lock_release(&evas_thread_queue_lock); goto out; } - eina_condition_wait(&evas_thread_queue_condition); + eina_condition_timedwait(&evas_thread_queue_condition, SHUTDOWN_TIMEOUT * 0.75); } if (!eina_inarray_count(&evas_thread_queue)) @@ -176,14 +177,20 @@ evas_thread_worker_func(void *data EINA_UNUSED, Eina_Thread thread EINA_UNUSED) } out: - /* WRN: add a memory barrier or use a lock if we add more code here */ + eina_lock_take(&evas_thread_exited_lock); evas_thread_exited = 1; + eina_lock_release(&evas_thread_exited_lock); return NULL; } static void evas_thread_fork_reset(void *data EINA_UNUSED) { + if (!eina_lock_new(&evas_thread_exited_lock)) + { + CRI("Could not create exit thread lock (%m)"); + goto on_error; + } if (!eina_lock_new(&evas_thread_queue_lock)) { CRI("Could not create draw thread lock (%m)"); @@ -205,6 +212,7 @@ evas_thread_fork_reset(void *data EINA_UNUSED) return ; on_error: + eina_lock_free(&evas_thread_exited_lock); eina_lock_free(&evas_thread_queue_lock); eina_condition_free(&evas_thread_queue_condition); @@ -237,6 +245,12 @@ evas_thread_init(void) eina_inarray_step_set(&evas_thread_queue, sizeof (Eina_Inarray), sizeof (Evas_Thread_Command), 128); + if (!eina_lock_new(&evas_thread_exited_lock)) + { + CRI("Could not create exit thread lock (%m)"); + goto fail_on_lock_creation; + } + if (!eina_lock_new(&evas_thread_queue_lock)) { CRI("Could not create draw thread lock (%m)"); @@ -263,6 +277,7 @@ fail_on_thread_creation: evas_thread_worker = 0; eina_condition_free(&evas_thread_queue_condition); fail_on_cond_creation: + eina_lock_free(&evas_thread_exited_lock); eina_lock_free(&evas_thread_queue_lock); fail_on_lock_creation: eina_threads_shutdown(); @@ -300,8 +315,13 @@ evas_thread_shutdown(void) eina_lock_release(&evas_thread_queue_lock); _shutdown_timeout(&to, SHUTDOWN_TIMEOUT_RESET, SHUTDOWN_TIMEOUT); - while (!evas_thread_exited && (evas_async_events_process() != -1)) + while (1) { + int exited; + eina_lock_take(&evas_thread_exited_lock); + exited = evas_thread_exited; + eina_lock_release(&evas_thread_exited_lock); + if (exited || (evas_async_events_process() == -1)) break; if(_shutdown_timeout(&to, SHUTDOWN_TIMEOUT_CHECK, SHUTDOWN_TIMEOUT)) { CRI("Timeout shutdown thread. Skipping thread_join. Some resources could be leaked"); @@ -311,6 +331,7 @@ evas_thread_shutdown(void) eina_thread_join(evas_thread_worker); timeout_shutdown: + eina_lock_free(&evas_thread_exited_lock); eina_lock_free(&evas_thread_queue_lock); eina_condition_free(&evas_thread_queue_condition); --
