ecore_thread: do not override the data field of a thread

otherwise a currently executed ecore_thread is going to pass a complete
wrong data to its callbacks.

fix T5175
fix T5173
This commit is contained in:
Marcel Hollerbach 2017-03-02 18:32:40 +01:00
parent 347c75fbe3
commit 097f9cfe5f
1 changed files with 20 additions and 20 deletions

View File

@ -49,6 +49,14 @@
typedef struct _Ecore_Pthread_Worker Ecore_Pthread_Worker; typedef struct _Ecore_Pthread_Worker Ecore_Pthread_Worker;
typedef struct _Ecore_Pthread Ecore_Pthread; typedef struct _Ecore_Pthread Ecore_Pthread;
typedef struct _Ecore_Thread_Data Ecore_Thread_Data; 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 struct _Ecore_Thread_Data
{ {
@ -87,6 +95,7 @@ struct _Ecore_Pthread_Worker
} message_run; } message_run;
} u; } u;
Ecore_Thread_Waiter *waiter;
Ecore_Thread_Cb func_cancel; Ecore_Thread_Cb func_cancel;
Ecore_Thread_Cb func_end; Ecore_Thread_Cb func_end;
PH(self); PH(self);
@ -352,13 +361,13 @@ _ecore_short_job(PH(thread))
int cancel; int cancel;
SLKL(_ecore_pending_job_threads_mutex); SLKL(_ecore_pending_job_threads_mutex);
if (!_ecore_pending_job_threads) if (!_ecore_pending_job_threads)
{ {
SLKU(_ecore_pending_job_threads_mutex); SLKU(_ecore_pending_job_threads_mutex);
return; return;
} }
work = eina_list_data_get(_ecore_pending_job_threads); 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 = eina_list_remove_list(_ecore_pending_job_threads,
_ecore_pending_job_threads); _ecore_pending_job_threads);
@ -793,46 +802,37 @@ ecore_thread_cancel(Ecore_Thread *thread)
return EINA_FALSE; 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;
Eina_Bool waiting;
};
static void static void
_ecore_thread_wait_reset(Ecore_Thread_Waiter *waiter, _ecore_thread_wait_reset(Ecore_Thread_Waiter *waiter,
Ecore_Pthread_Worker *worker) Ecore_Pthread_Worker *worker)
{ {
worker->data = waiter->data;
worker->func_cancel = waiter->func_cancel; worker->func_cancel = waiter->func_cancel;
worker->func_end = waiter->func_end; worker->func_end = waiter->func_end;
worker->waiter = NULL;
waiter->func_end = NULL; waiter->func_end = NULL;
waiter->func_cancel = NULL; waiter->func_cancel = NULL;
waiter->data = NULL;
waiter->waiting = EINA_FALSE; waiter->waiting = EINA_FALSE;
} }
static void 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_Pthread_Worker *worker = (Ecore_Pthread_Worker*) thread;
Ecore_Thread_Waiter *waiter = data; Ecore_Thread_Waiter *waiter = worker->waiter;
if (waiter->func_cancel) waiter->func_cancel((void*) waiter->data, thread); if (waiter->func_cancel) waiter->func_cancel(data, thread);
_ecore_thread_wait_reset(waiter, worker); _ecore_thread_wait_reset(waiter, worker);
} }
static void 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_Pthread_Worker *worker = (Ecore_Pthread_Worker*) thread;
Ecore_Thread_Waiter *waiter = data; Ecore_Thread_Waiter *waiter = worker->waiter;
if (waiter->func_end) waiter->func_end((void*) waiter->data, thread); if (waiter->func_end) waiter->func_end(data, thread);
_ecore_thread_wait_reset(waiter, worker); _ecore_thread_wait_reset(waiter, worker);
} }
@ -844,12 +844,12 @@ ecore_thread_wait(Ecore_Thread *thread, double wait)
if (!thread) return EINA_TRUE; if (!thread) return EINA_TRUE;
waiter.data = worker->data;
waiter.func_end = worker->func_end; waiter.func_end = worker->func_end;
waiter.func_cancel = worker->func_cancel; waiter.func_cancel = worker->func_cancel;
waiter.waiting = EINA_TRUE; waiter.waiting = EINA_TRUE;
// Now trick the thread to call the wrapper function // Now trick the thread to call the wrapper function
worker->data = &waiter; worker->waiter = &waiter;
worker->func_cancel = _ecore_thread_wait_cancel; worker->func_cancel = _ecore_thread_wait_cancel;
worker->func_end = _ecore_thread_wait_end; worker->func_end = _ecore_thread_wait_end;