forked from enlightenment/efl
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:
parent
8b9fe4adda
commit
88e1fc9613
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue