summaryrefslogtreecommitdiff
path: root/src/lib/evas/common
diff options
context:
space:
mode:
authorWonki Kim <wonki_.kim@samsung.com>2016-11-22 14:33:48 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2016-11-22 14:50:38 +0900
commit88e1fc9613389a264c69b159f5066476690c5af2 (patch)
tree6f99fbfab0d21a9d676567ce9db87dfd79065567 /src/lib/evas/common
parent8b9fe4addaf700ea4f7f605e5b148d7d4e47409e (diff)
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>
Diffstat (limited to 'src/lib/evas/common')
-rw-r--r--src/lib/evas/common/evas_thread_render.c91
1 files changed, 78 insertions, 13 deletions
diff --git a/src/lib/evas/common/evas_thread_render.c b/src/lib/evas/common/evas_thread_render.c
index 99c6b95c3c..d2d8581240 100644
--- a/src/lib/evas/common/evas_thread_render.c
+++ b/src/lib/evas/common/evas_thread_render.c
@@ -14,6 +14,23 @@ static volatile int evas_thread_exited = 0;
14static Eina_Bool exit_thread = EINA_FALSE; 14static Eina_Bool exit_thread = EINA_FALSE;
15static int init_count = 0; 15static int init_count = 0;
16 16
17#define SHUTDOWN_TIMEOUT_RESET (0)
18#define SHUTDOWN_TIMEOUT_CHECK (1)
19#define SHUTDOWN_TIMEOUT (3000)
20
21static Eina_Bool
22_shutdown_timeout(double *time, int mode, int timeout_ms)
23{
24 struct timeval tv;
25
26 gettimeofday(&tv, NULL);
27
28 if ( mode == SHUTDOWN_TIMEOUT_RESET )
29 *time = (tv.tv_sec + tv.tv_usec / 1000000.0) * 1000.0;
30 return ((tv.tv_sec + tv.tv_usec / 1000000.0) * 1000.0 - (*time)) > timeout_ms ;
31}
32
33
17static void 34static void
18evas_thread_queue_append(Evas_Thread_Command_Cb cb, void *data, Eina_Bool do_flush) 35evas_thread_queue_append(Evas_Thread_Command_Cb cb, void *data, Eina_Bool do_flush)
19{ 36{
@@ -122,32 +139,69 @@ out:
122 return NULL; 139 return NULL;
123} 140}
124 141
125void 142int
126evas_thread_init(void) 143evas_thread_init(void)
127{ 144{
128 if (init_count++) return; 145 if (init_count++)
146 return init_count;
129 147
130 eina_threads_init(); 148 exit_thread = EINA_FALSE;
149 evas_thread_exited = 0;
150
151 if(!eina_threads_init())
152 {
153 CRI("Could not init eina threads");
154 goto fail_on_eina_thread_init;
155 }
131 156
132 eina_inarray_step_set(&evas_thread_queue, sizeof (Eina_Inarray), sizeof (Evas_Thread_Command), 128); 157 eina_inarray_step_set(&evas_thread_queue, sizeof (Eina_Inarray), sizeof (Evas_Thread_Command), 128);
133 158
134 if (!eina_lock_new(&evas_thread_queue_lock)) 159 if (!eina_lock_new(&evas_thread_queue_lock))
135 CRI("Could not create draw thread lock"); 160 {
161 CRI("Could not create draw thread lock (%m)");
162 goto fail_on_lock_creation;
163 }
136 if (!eina_condition_new(&evas_thread_queue_condition, &evas_thread_queue_lock)) 164 if (!eina_condition_new(&evas_thread_queue_condition, &evas_thread_queue_lock))
137 CRI("Could not create draw thread condition"); 165 {
166 CRI("Could not create draw thread condition (%m)");
167 goto fail_on_cond_creation;
168 }
138 169
139 if (!eina_thread_create(&evas_thread_worker, EINA_THREAD_NORMAL, -1, 170 if (!eina_thread_create(&evas_thread_worker, EINA_THREAD_NORMAL, -1,
140 evas_thread_worker_func, NULL)) 171 evas_thread_worker_func, NULL))
141 CRI("Could not create draw thread"); 172 {
173 CRI("Could not create draw thread (%m)");
174 goto fail_on_thread_creation;
175 }
176
177 return init_count;
178
179fail_on_thread_creation:
180 evas_thread_worker = 0;
181 eina_condition_free(&evas_thread_queue_condition);
182fail_on_cond_creation:
183 eina_lock_free(&evas_thread_queue_lock);
184fail_on_lock_creation:
185 eina_threads_shutdown();
186fail_on_eina_thread_init:
187 exit_thread = EINA_TRUE;
188 evas_thread_exited = 1;
189 return --init_count;
142} 190}
143 191
144void 192int
145evas_thread_shutdown(void) 193evas_thread_shutdown(void)
146{ 194{
147 assert(init_count); 195 double to = 0 ;
196
197 if (init_count <= 0)
198 {
199 ERR("Too many calls to shutdown, ignored.");
200 return 0;
201 }
148 202
149 if (--init_count) 203 if (--init_count)
150 return; 204 return init_count;
151 205
152 eina_lock_take(&evas_thread_queue_lock); 206 eina_lock_take(&evas_thread_queue_lock);
153 207
@@ -155,16 +209,27 @@ evas_thread_shutdown(void)
155 eina_condition_signal(&evas_thread_queue_condition); 209 eina_condition_signal(&evas_thread_queue_condition);
156 210
157 eina_lock_release(&evas_thread_queue_lock); 211 eina_lock_release(&evas_thread_queue_lock);
158 212 _shutdown_timeout(&to, SHUTDOWN_TIMEOUT_RESET, SHUTDOWN_TIMEOUT);
159 while (!evas_thread_exited) 213 while (!evas_thread_exited && (evas_async_events_process() != -1))
160 evas_async_events_process(); 214 {
215 if(_shutdown_timeout(&to, SHUTDOWN_TIMEOUT_CHECK, SHUTDOWN_TIMEOUT))
216 {
217 CRI("Timeout shutdown thread. Skipping thread_join. Some resources could be leaked");
218 goto timeout_shutdown;
219 }
220 }
161 221
162 eina_thread_join(evas_thread_worker); 222 eina_thread_join(evas_thread_worker);
223timeout_shutdown:
163 eina_lock_free(&evas_thread_queue_lock); 224 eina_lock_free(&evas_thread_queue_lock);
164 eina_condition_free(&evas_thread_queue_condition); 225 eina_condition_free(&evas_thread_queue_condition);
165 226
227 evas_thread_worker = 0;
228
166 eina_inarray_flush(&evas_thread_queue); 229 eina_inarray_flush(&evas_thread_queue);
167 free(evas_thread_queue_cache); 230 free(evas_thread_queue_cache);
168 231
169 eina_threads_shutdown(); 232 eina_threads_shutdown();
233
234 return 0;
170} 235}