evas: Add shutdown logic on thread creation failure

Summary:
In case of thread creation failure, shutdown logic will be stuck.
To prevent stuck, set exit variables to make thread_shutdown working
even if init fails.

Also modify init logics to return init result to a caller.

Reviewers: jypark, woohyun, cedric, jpeg

Subscribers: cedric

Differential Revision: https://phab.enlightenment.org/D4411

Note (@jpeg):
I have modified the patch just a little bit.

Signed-off-by: Jean-Philippe Andre <jp.andre@samsung.com>
This commit is contained in:
Wonki Kim 2016-11-22 14:33:48 +09:00 committed by Jean-Philippe Andre
parent 8b9fe4adda
commit 88e1fc9613
5 changed files with 112 additions and 29 deletions

View File

@ -236,7 +236,7 @@ evas_async_events_process(void)
{ {
int nr, count = 0; int nr, count = 0;
if (_fd_read == -1) return 0; if (_fd_read == -1) return -1;
_evas_async_events_fork_handle(); _evas_async_events_fork_handle();

View File

@ -66,16 +66,22 @@ evas_init(void)
if (!evas_async_events_init()) if (!evas_async_events_init())
goto shutdown_module; goto shutdown_module;
#ifdef EVAS_CSERVE2 #ifdef EVAS_CSERVE2
int cs2 = 0;
{ {
const char *env; const char *env;
env = getenv("EVAS_CSERVE2"); env = getenv("EVAS_CSERVE2");
if (env && atoi(env)) evas_cserve2_init(); if (env && atoi(env))
{
cs2 = evas_cserve2_init();
if (!cs2) goto shutdown_async_events;
}
} }
#endif #endif
_evas_preload_thread_init(); _evas_preload_thread_init();
evas_filter_init(); evas_filter_init();
evas_thread_init(); if (!evas_thread_init())
goto shutdown_filter;
eina_log_timing(_evas_log_dom_global, eina_log_timing(_evas_log_dom_global,
EINA_LOG_STATE_STOP, EINA_LOG_STATE_STOP,
@ -83,8 +89,20 @@ evas_init(void)
return _evas_init_count; return _evas_init_count;
shutdown_filter:
evas_filter_shutdown();
_evas_preload_thread_shutdown();
#ifdef EVAS_CSERVE2
if (cs2) evas_cserve2_shutdown();
shutdown_async_events:
#endif
evas_async_events_shutdown();
shutdown_module: shutdown_module:
evas_module_shutdown(); evas_module_shutdown();
#ifdef BUILD_LOADER_EET
eet_shutdown();
#endif
efl_object_shutdown();
eina_log_domain_unregister(_evas_log_dom_global); eina_log_domain_unregister(_evas_log_dom_global);
shutdown_eet: shutdown_eet:
eet_shutdown(); eet_shutdown();

View File

@ -14,6 +14,23 @@ static volatile int evas_thread_exited = 0;
static Eina_Bool exit_thread = EINA_FALSE; static Eina_Bool exit_thread = EINA_FALSE;
static int init_count = 0; static int init_count = 0;
#define SHUTDOWN_TIMEOUT_RESET (0)
#define SHUTDOWN_TIMEOUT_CHECK (1)
#define SHUTDOWN_TIMEOUT (3000)
static Eina_Bool
_shutdown_timeout(double *time, int mode, int timeout_ms)
{
struct timeval tv;
gettimeofday(&tv, NULL);
if ( mode == SHUTDOWN_TIMEOUT_RESET )
*time = (tv.tv_sec + tv.tv_usec / 1000000.0) * 1000.0;
return ((tv.tv_sec + tv.tv_usec / 1000000.0) * 1000.0 - (*time)) > timeout_ms ;
}
static void static void
evas_thread_queue_append(Evas_Thread_Command_Cb cb, void *data, Eina_Bool do_flush) evas_thread_queue_append(Evas_Thread_Command_Cb cb, void *data, Eina_Bool do_flush)
{ {
@ -122,32 +139,69 @@ out:
return NULL; return NULL;
} }
void int
evas_thread_init(void) evas_thread_init(void)
{ {
if (init_count++) return; if (init_count++)
return init_count;
eina_threads_init(); exit_thread = EINA_FALSE;
evas_thread_exited = 0;
if(!eina_threads_init())
{
CRI("Could not init eina threads");
goto fail_on_eina_thread_init;
}
eina_inarray_step_set(&evas_thread_queue, sizeof (Eina_Inarray), sizeof (Evas_Thread_Command), 128); eina_inarray_step_set(&evas_thread_queue, sizeof (Eina_Inarray), sizeof (Evas_Thread_Command), 128);
if (!eina_lock_new(&evas_thread_queue_lock)) if (!eina_lock_new(&evas_thread_queue_lock))
CRI("Could not create draw thread lock"); {
CRI("Could not create draw thread lock (%m)");
goto fail_on_lock_creation;
}
if (!eina_condition_new(&evas_thread_queue_condition, &evas_thread_queue_lock)) if (!eina_condition_new(&evas_thread_queue_condition, &evas_thread_queue_lock))
CRI("Could not create draw thread condition"); {
CRI("Could not create draw thread condition (%m)");
goto fail_on_cond_creation;
}
if (!eina_thread_create(&evas_thread_worker, EINA_THREAD_NORMAL, -1, if (!eina_thread_create(&evas_thread_worker, EINA_THREAD_NORMAL, -1,
evas_thread_worker_func, NULL)) evas_thread_worker_func, NULL))
CRI("Could not create draw thread"); {
CRI("Could not create draw thread (%m)");
goto fail_on_thread_creation;
}
return init_count;
fail_on_thread_creation:
evas_thread_worker = 0;
eina_condition_free(&evas_thread_queue_condition);
fail_on_cond_creation:
eina_lock_free(&evas_thread_queue_lock);
fail_on_lock_creation:
eina_threads_shutdown();
fail_on_eina_thread_init:
exit_thread = EINA_TRUE;
evas_thread_exited = 1;
return --init_count;
} }
void int
evas_thread_shutdown(void) evas_thread_shutdown(void)
{ {
assert(init_count); double to = 0 ;
if (init_count <= 0)
{
ERR("Too many calls to shutdown, ignored.");
return 0;
}
if (--init_count) if (--init_count)
return; return init_count;
eina_lock_take(&evas_thread_queue_lock); eina_lock_take(&evas_thread_queue_lock);
@ -155,16 +209,27 @@ evas_thread_shutdown(void)
eina_condition_signal(&evas_thread_queue_condition); eina_condition_signal(&evas_thread_queue_condition);
eina_lock_release(&evas_thread_queue_lock); eina_lock_release(&evas_thread_queue_lock);
_shutdown_timeout(&to, SHUTDOWN_TIMEOUT_RESET, SHUTDOWN_TIMEOUT);
while (!evas_thread_exited) while (!evas_thread_exited && (evas_async_events_process() != -1))
evas_async_events_process(); {
if(_shutdown_timeout(&to, SHUTDOWN_TIMEOUT_CHECK, SHUTDOWN_TIMEOUT))
{
CRI("Timeout shutdown thread. Skipping thread_join. Some resources could be leaked");
goto timeout_shutdown;
}
}
eina_thread_join(evas_thread_worker); eina_thread_join(evas_thread_worker);
timeout_shutdown:
eina_lock_free(&evas_thread_queue_lock); eina_lock_free(&evas_thread_queue_lock);
eina_condition_free(&evas_thread_queue_condition); eina_condition_free(&evas_thread_queue_condition);
evas_thread_worker = 0;
eina_inarray_flush(&evas_thread_queue); eina_inarray_flush(&evas_thread_queue);
free(evas_thread_queue_cache); free(evas_thread_queue_cache);
eina_threads_shutdown(); eina_threads_shutdown();
return 0;
} }

View File

@ -1315,8 +1315,8 @@ EAPI int evas_async_events_process_blocking(void);
void evas_render_rendering_wait(Evas_Public_Data *evas); void evas_render_rendering_wait(Evas_Public_Data *evas);
void evas_all_sync(void); void evas_all_sync(void);
void evas_thread_init(void); int evas_thread_init(void);
void evas_thread_shutdown(void); int evas_thread_shutdown(void);
EAPI void evas_thread_cmd_enqueue(Evas_Thread_Command_Cb cb, void *data); EAPI void evas_thread_cmd_enqueue(Evas_Thread_Command_Cb cb, void *data);
EAPI void evas_thread_queue_flush(Evas_Thread_Command_Cb cb, void *data); EAPI void evas_thread_queue_flush(Evas_Thread_Command_Cb cb, void *data);