ecore: force pthread_join even when main loop isn't running.
authorcedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 30 May 2012 12:14:34 +0000 (12:14 +0000)
committercedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 30 May 2012 12:14:34 +0000 (12:14 +0000)
pthread_create can fail if to much pthread are pending. As pthread_join
is only called when the main loop can flush the async call list, there was
a possibility for edje_cc to run out of thread due to that. We know
force the flush of the async call list and so call pthread_join when
pthread_create fail.

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/ecore@71555 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

ChangeLog
NEWS
src/lib/ecore/ecore.c
src/lib/ecore/ecore_private.h
src/lib/ecore/ecore_thread.c

index ec93cb5..ed2826b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
 2012-05-30  Cedric Bail
 
        * Force cancel of all running Ecore_Thread on shutdown.
+       * Make Ecore_Thread work reliabily when main loop isn't running.
 
 2012-05-30  Mariusz Grzegorczyk
 
diff --git a/NEWS b/NEWS
index 1fa6a41..0aeebdc 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -16,6 +16,7 @@ Fixes:
      - Send mouse move event before mouse down event in ecore_extn
      - Reduce race condition on shutdown of Ecore_Thread.
      - Force cancel of all running Ecore_Thread on shutdown.
+     - Make Ecore_Thread work reliably when called without a running main loop.
 
 Ecore 1.2.0
 
index 5dfe3d6..7a221e3 100644 (file)
@@ -709,10 +709,8 @@ _thread_safe_cleanup(void *data)
    eina_lock_free(&call->m);
 }
 
-static void
-_thread_callback(void        *data __UNUSED__,
-                 void        *buffer __UNUSED__,
-                 unsigned int nbyte __UNUSED__)
+void
+_ecore_main_call_flush(void)
 {
    Ecore_Safe_Call *call;
    Eina_List *callback;
@@ -762,3 +760,11 @@ _thread_callback(void        *data __UNUSED__,
      }
 }
 
+static void
+_thread_callback(void        *data __UNUSED__,
+                 void        *buffer __UNUSED__,
+                 unsigned int nbyte __UNUSED__)
+{
+   _ecore_main_call_flush();
+}
+
index a35d12e..d812e3a 100644 (file)
@@ -224,6 +224,8 @@ void _ecore_main_loop_shutdown(void);
 
 void _ecore_throttle(void);
 
+void _ecore_main_call_flush(void);
+
 extern int _ecore_main_lock_count;
 extern Eina_Lock _ecore_main_loop_lock;
 
index 407e84b..e2c4914 100644 (file)
@@ -168,7 +168,7 @@ struct _Ecore_Pthread_Worker
 
    const void     *data;
 
-   volatile int cancel;
+   int cancel;
 
 #ifdef EFL_HAVE_THREADS
    LK(cancel_mutex);
@@ -280,7 +280,7 @@ _ecore_thread_data_free(void *data)
 static void
 _ecore_thread_join(PH(thread))
 {
-  PHJ(thread);
+   PHJ(thread);
 }
 
 static void
@@ -674,6 +674,7 @@ ecore_thread_run(Ecore_Thread_Cb func_blocking,
                  const void     *data)
 {
    Ecore_Pthread_Worker *work;
+   Eina_Bool tried = EINA_FALSE;
 #ifdef EFL_HAVE_THREADS
    PH(thread);
 #endif
@@ -721,17 +722,20 @@ ecore_thread_run(Ecore_Thread_Cb func_blocking,
 
    LKL(_ecore_pending_job_threads_mutex);
 
+ retry:
    if (PHC(thread, _ecore_thread_worker, NULL) == 0)
      {
         _ecore_thread_count++;
        LKU(_ecore_pending_job_threads_mutex);
         return (Ecore_Thread *)work;
      }
-   LKU(_ecore_pending_job_threads_mutex);
-
-   eina_threads_shutdown();
+   if (!tried)
+     {
+       _ecore_main_call_flush();
+       tried = EINA_TRUE;
+       goto retry;
+     }
 
-   LKL(_ecore_pending_job_threads_mutex);
    if (_ecore_thread_count == 0)
      {
         _ecore_pending_job_threads = eina_list_remove(_ecore_pending_job_threads, work);
@@ -746,6 +750,9 @@ ecore_thread_run(Ecore_Thread_Cb func_blocking,
         work = NULL;
      }
    LKU(_ecore_pending_job_threads_mutex);
+
+   eina_threads_shutdown();
+
    return (Ecore_Thread *)work;
 #else
    /*
@@ -882,6 +889,7 @@ ecore_thread_feedback_run(Ecore_Thread_Cb        func_heavy,
 {
 #ifdef EFL_HAVE_THREADS
    Ecore_Pthread_Worker *worker;
+   Eina_Bool tried = EINA_FALSE;
    PH(thread);
 
    EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
@@ -918,8 +926,15 @@ ecore_thread_feedback_run(Ecore_Thread_Cb        func_heavy,
 
         eina_threads_init();
 
+     retry_direct:
         if (PHC(t, _ecore_direct_worker, worker) == 0)
           return (Ecore_Thread *)worker;
+       if (!tried)
+         {
+            _ecore_main_call_flush();
+            tried = EINA_TRUE;
+            goto retry_direct;
+         }
 
         if (worker->u.feedback_run.direct_worker)
           {
@@ -947,12 +962,19 @@ ecore_thread_feedback_run(Ecore_Thread_Cb        func_heavy,
    eina_threads_init();
 
    LKL(_ecore_pending_job_threads_mutex);
+ retry:
    if (PHC(thread, _ecore_thread_worker, NULL) == 0)
      {
         _ecore_thread_count++;
        LKU(_ecore_pending_job_threads_mutex);
         return (Ecore_Thread *)worker;
      }
+   if (!tried)
+     {
+        _ecore_main_call_flush();
+       tried = EINA_TRUE;
+       goto retry;
+     }
    LKU(_ecore_pending_job_threads_mutex);
 
    eina_threads_shutdown();