Fix data race on worker::queue::priv::bring_workers_down
authorDodji Seketeli <dodji@redhat.com>
Wed, 15 Mar 2017 15:15:37 +0000 (16:15 +0100)
committerDodji Seketeli <dodji@redhat.com>
Wed, 15 Mar 2017 15:15:37 +0000 (16:15 +0100)
When one thread calls queue::wait_to_execute_a_task and another calls
queue::priv::do_bring_workers_down, a data race occurs on the
queue::priv::bring_workers_down variable.

This patch protects the read of the queue::priv::bring_workers_down
variable (in worker::wait_to_execute_a_task) by the
queue::priv::tasks_todo_mutex mutex.  Note that that mutex is the one
that protects the write to queue::priv::bring_workers_down in
queue::priv::do_bring_workers_down.

* src/abg-workers.cc (worker::wait_to_execute_a_task): Protect the
read of the queue::priv::bring_workers_down down variable with the
queue::priv::tasks_todo_mutex.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
src/abg-workers.cc

index 3df8c5d177e4e75318a41c941066b3a8b0014697..34ef1fd5f038401da77446d03b6ec492ef91570f 100644 (file)
@@ -430,22 +430,25 @@ worker::wait_to_execute_a_task(queue::priv* p)
 {
   pthread_mutex_lock(&p->tasks_todo_mutex);
   bool more_tasks = !p->tasks_todo.empty();
+  bool bring_workers_down = p->bring_workers_down;
   pthread_mutex_unlock(&p->tasks_todo_mutex);
 
   do
     {
       // If there is no more tasks to perform and the queue is not to
       // be brought down then wait (sleep) for new tasks to come up.
-      pthread_mutex_lock(&p->queue_cond_mutex);
-      while (!more_tasks && !p->bring_workers_down)
+      while (!more_tasks && !bring_workers_down)
        {
+         pthread_mutex_lock(&p->queue_cond_mutex);
          pthread_cond_wait(&p->queue_cond, &p->queue_cond_mutex);
+         pthread_mutex_unlock(&p->queue_cond_mutex);
 
          pthread_mutex_lock(&p->tasks_todo_mutex);
          more_tasks = !p->tasks_todo.empty();
+         bring_workers_down = p->bring_workers_down;
          pthread_mutex_unlock(&p->tasks_todo_mutex);
        }
-      pthread_mutex_unlock(&p->queue_cond_mutex);
+
 
       // We were woken up.  So maybe there are tasks to perform?  If
       // so, get a task from the queue ...
@@ -480,6 +483,7 @@ worker::wait_to_execute_a_task(queue::priv* p)
 
       pthread_mutex_lock(&p->tasks_todo_mutex);
       more_tasks = !p->tasks_todo.empty();
+      bring_workers_down = p->bring_workers_down;
       pthread_mutex_unlock(&p->tasks_todo_mutex);
     }
     while (!p->bring_workers_down || more_tasks);