ecore: cancel all pending thread at shutdown.
authorcedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 30 May 2012 03:10:30 +0000 (03:10 +0000)
committercedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 30 May 2012 03:10:30 +0000 (03:10 +0000)
Hopefully this will fix bug #961.

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

ChangeLog
NEWS
src/lib/ecore/ecore_thread.c

index 8fd05a4..43d7962 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
 
        * Reduce race condition on Ecore_Thread shutdown.
 
-2012-05-22 Carsten Haitzler (The Rasterman)
+2012-05-22  Carsten Haitzler (The Rasterman)
 
         * Add ecore_x_mouse_in_send() and ecore_x_mouse_out_send()
         * Add ecore_x illume access control/action atoms+api's
 
-2012-05-24 Doyoun Kang
+2012-05-24  Doyoun Kang
 
         * Add Ecore_X_Error_Code enumeration in ecore_x
 
-2012-05-24 Carsten Haitzler (The Rasterman)
+2012-05-24  Carsten Haitzler (The Rasterman)
 
         * Add ecore_con_client_ref() and ecore_con_client_unref()
         * Fix ecore_con to obey reference counting for con clients
         so now have fairer scheduling.
         * Allow 16 * cpu num for worker threads (default still cpu num)
 
-2012-05-25 Carsten Haitzler (The Rasterman)
+2012-05-25  Carsten Haitzler (The Rasterman)
 
         * Fix ecore mainloop issue if you begin the mainloop, keep a
         timer around, quit mainloop, then start it again expecting the timer
         to keep ticking off. also happens to be an issue with
         iterating the mainloop.
 
-2012-05-25 Rob Bradford
+2012-05-25  Rob Bradford
 
         * Make ecore_{software_x11, software_x11_8, software_x11_16, wayland,
         directfb}_window_get return 0 if the Ecore_Evas was not created with
         the appropriate constructor.
 
+2012-05-30  Cedric Bail
+
+       * Force cancel of all running Ecore_Thread on shutdown.
diff --git a/NEWS b/NEWS
index aaec5d9..1fa6a41 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -15,6 +15,7 @@ Fixes:
      - Reduce rounding error in ecore_animator_pos_map.
      - 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.
 
 Ecore 1.2.0
 
index 78f74f3..bb7e7d7 100644 (file)
@@ -217,6 +217,7 @@ static void _ecore_thread_handler(void *data);
 
 static int _ecore_thread_count = 0;
 
+static Eina_List *_ecore_running_job = NULL;
 static Eina_List *_ecore_pending_job_threads = NULL;
 static Eina_List *_ecore_pending_job_threads_feedback = NULL;
 static LK(_ecore_pending_job_threads_mutex);
@@ -412,7 +413,7 @@ _ecore_short_job(PH(thread))
    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);
-   
+   _ecore_running_job = eina_list_append(_ecore_running_job, work);
    LKU(_ecore_pending_job_threads_mutex);
    
    LKL(work->cancel_mutex);
@@ -421,6 +422,10 @@ _ecore_short_job(PH(thread))
    work->self = thread;
    if (!cancel)
      work->u.short_run.func_blocking((void *) work->data, (Ecore_Thread*) work);
+
+   LKL(_ecore_pending_job_threads_mutex);
+   _ecore_running_job = eina_list_remove(_ecore_running_job, work);
+   LKU(_ecore_pending_job_threads_mutex);
    
    if (work->reschedule)
      {
@@ -453,7 +458,7 @@ _ecore_feedback_job(PH(thread))
    work = eina_list_data_get(_ecore_pending_job_threads_feedback);
    _ecore_pending_job_threads_feedback = eina_list_remove_list(_ecore_pending_job_threads_feedback,
                                                                _ecore_pending_job_threads_feedback);
-   
+   _ecore_running_job = eina_list_append(_ecore_running_job, work);
    LKU(_ecore_pending_job_threads_mutex);
    
    LKL(work->cancel_mutex);
@@ -462,7 +467,11 @@ _ecore_feedback_job(PH(thread))
    work->self = thread;
    if (!cancel)
      work->u.feedback_run.func_heavy((void *) work->data, (Ecore_Thread *) work);
-   
+
+   LKL(_ecore_pending_job_threads_mutex);
+   _ecore_running_job = eina_list_remove(_ecore_running_job, work);
+   LKU(_ecore_pending_job_threads_mutex);
+
    if (work->reschedule)
      {
         work->reschedule = EINA_FALSE;
@@ -539,10 +548,10 @@ restart:
         goto restart;
      }
    _ecore_thread_count--;
-   LKU(_ecore_pending_job_threads_mutex);
 
    ecore_main_loop_thread_safe_call_async((Ecore_Cb) _ecore_thread_join,
                                          (void*) PHS());
+   LKU(_ecore_pending_job_threads_mutex);
 
    return NULL;
 }
@@ -591,6 +600,9 @@ _ecore_thread_shutdown(void)
    /* FIXME: If function are still running in the background, should we kill them ? */
 #ifdef EFL_HAVE_THREADS
     Ecore_Pthread_Worker *work;
+    Eina_List *l;
+    Eina_Bool test;
+    int iteration = 0;
 
     LKL(_ecore_pending_job_threads_mutex);
 
@@ -608,9 +620,33 @@ _ecore_thread_shutdown(void)
          free(work);
       }
 
+    EINA_LIST_FOREACH(_ecore_running_job, l, work)
+      ecore_thread_cancel((Ecore_Thread*) work);
+
     LKU(_ecore_pending_job_threads_mutex);
 
-    /* FIXME: Improve emergency shutdown, now that we use async call, we can do something */
+    do
+      {
+        LKL(_ecore_pending_job_threads_mutex);
+        if (_ecore_thread_count > 0)
+          {
+             test = EINA_TRUE;
+          }
+        else
+          {
+             test = EINA_FALSE;
+          }
+        LKU(_ecore_pending_job_threads_mutex);
+        iteration++;
+        if (test) usleep(50000);
+      }
+    while (test == EINA_TRUE && iteration < 20);
+
+    if (iteration == 20 && _ecore_thread_count > 0)
+      {
+        ERR("%i of the child thread are still running after 1s. This can lead to a segv. Sorry.", _ecore_thread_count);
+      }
+
     if (_ecore_thread_global_hash)
       eina_hash_free(_ecore_thread_global_hash);
     have_main_loop_thread = 0;