ecore_thread: do not override the data field of a thread 80/149880/2
authorMarcel Hollerbach <marcel-hollerbach@t-online.de>
Thu, 2 Mar 2017 17:32:40 +0000 (18:32 +0100)
committerHosang Kim <hosang12.kim@samsung.com>
Wed, 13 Sep 2017 12:02:32 +0000 (21:02 +0900)
otherwise a currently executed ecore_thread is going to pass a complete
wrong data to its callbacks.

fix T5175
fix T5173

Upstream: 097f9cfe5fa601deaca1ed4c72c6311b4b893386

Change-Id: I427d6440c265e358cd0268f24e1c4f27bf23c4f0

src/lib/ecore/ecore_thread.c

index befb0fb..9ef8e3c 100644 (file)
 typedef struct _Ecore_Pthread_Worker Ecore_Pthread_Worker;
 typedef struct _Ecore_Pthread        Ecore_Pthread;
 typedef struct _Ecore_Thread_Data    Ecore_Thread_Data;
+typedef struct _Ecore_Thread_Waiter Ecore_Thread_Waiter;
+
+struct _Ecore_Thread_Waiter
+{
+   Ecore_Thread_Cb func_cancel;
+   Ecore_Thread_Cb func_end;
+   Eina_Bool waiting;
+};
 
 struct _Ecore_Thread_Data
 {
@@ -87,6 +95,7 @@ struct _Ecore_Pthread_Worker
       } message_run;
    } u;
 
+   Ecore_Thread_Waiter *waiter;
    Ecore_Thread_Cb func_cancel;
    Ecore_Thread_Cb func_end;
                    PH(self);
@@ -326,13 +335,13 @@ _ecore_short_job(PH(thread))
    int cancel;
 
    SLKL(_ecore_pending_job_threads_mutex);
-   
+
    if (!_ecore_pending_job_threads)
      {
         SLKU(_ecore_pending_job_threads_mutex);
         return;
      }
-   
+
    work = eina_list_data_get(_ecore_pending_job_threads);
    _ecore_pending_job_threads = eina_list_remove_list(_ecore_pending_job_threads,
                                                       _ecore_pending_job_threads);
@@ -735,44 +744,36 @@ ecore_thread_cancel(Ecore_Thread *thread)
    return EINA_FALSE;
 }
 
-typedef struct _Ecore_Thread_Waiter Ecore_Thread_Waiter;
-struct _Ecore_Thread_Waiter
-{
-   Ecore_Thread_Cb func_cancel;
-   Ecore_Thread_Cb func_end;
-   const void *data;
-};
-
 static void
 _ecore_thread_wait_reset(Ecore_Thread_Waiter *waiter,
                          Ecore_Pthread_Worker *worker)
 {
-   worker->data = waiter->data;
    worker->func_cancel = waiter->func_cancel;
    worker->func_end = waiter->func_end;
-   // The waiter will be checked by _wait, NULL meaning it is done
+   worker->waiter = NULL;
+
    waiter->func_end = NULL;
    waiter->func_cancel = NULL;
-   waiter->data = NULL;
+   waiter->waiting = EINA_FALSE;
 }
 
 static void
-_ecore_thread_wait_cancel(void *data, Ecore_Thread *thread)
+_ecore_thread_wait_cancel(void *data EINA_UNUSED, Ecore_Thread *thread)
 {
    Ecore_Pthread_Worker *worker = (Ecore_Pthread_Worker*) thread;
-   Ecore_Thread_Waiter *waiter = data;
+   Ecore_Thread_Waiter *waiter = worker->waiter;
 
-   waiter->func_cancel((void*) waiter->data, thread);
+   if (waiter->func_cancel) waiter->func_cancel(data, thread);
    _ecore_thread_wait_reset(waiter, worker);
 }
 
 static void
-_ecore_thread_wait_end(void *data, Ecore_Thread *thread)
+_ecore_thread_wait_end(void *data EINA_UNUSED, Ecore_Thread *thread)
 {
    Ecore_Pthread_Worker *worker = (Ecore_Pthread_Worker*) thread;
-   Ecore_Thread_Waiter *waiter = data;
+   Ecore_Thread_Waiter *waiter = worker->waiter;
 
-   waiter->func_end((void*) waiter->data, thread);
+   if (waiter->func_end) waiter->func_end(data, thread);
    _ecore_thread_wait_reset(waiter, worker);
 }
 
@@ -784,15 +785,16 @@ ecore_thread_wait(Ecore_Thread *thread, double wait)
 
    if (!thread) return EINA_TRUE;
 
-   waiter.data = worker->data;
    waiter.func_end = worker->func_end;
    waiter.func_cancel = worker->func_cancel;
+   waiter.waiting = EINA_TRUE;
+
    // Now trick the thread to call the wrapper function
-   worker->data = &waiter;
+   worker->waiter = &waiter;
    worker->func_cancel = _ecore_thread_wait_cancel;
    worker->func_end = _ecore_thread_wait_end;
 
-   while (waiter.data)
+   while (waiter.waiting == EINA_TRUE)
      {
         double start, end;
 
@@ -805,7 +807,15 @@ ecore_thread_wait(Ecore_Thread *thread, double wait)
         if (wait <= 0) break;
      }
 
-   return (waiter.data == NULL) ? EINA_TRUE : EINA_FALSE;
+   if (waiter.waiting == EINA_FALSE)
+     {
+        return EINA_TRUE;
+     }
+   else
+     {
+        _ecore_thread_wait_reset(&waiter, worker);
+        return EINA_FALSE;
+     }
 }
 
 EAPI Eina_Bool