]> git.proxmox.com Git - mirror_frr.git/commitdiff
lib: enforce thread_cancel() MT-unsafe invariant
authorQuentin Young <qlyoung@cumulusnetworks.com>
Wed, 17 May 2017 17:11:34 +0000 (17:11 +0000)
committerQuentin Young <qlyoung@cumulusnetworks.com>
Fri, 19 May 2017 19:10:21 +0000 (19:10 +0000)
Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
lib/thread.c
lib/thread.h

index 2843a9211ee88f6d1600eb10c0a939bbd40a71f5..ccb635a87dff7af71052f9df98ef876cf9e0d3fa 100644 (file)
@@ -377,6 +377,7 @@ thread_master_create (void)
   rv->timer->update = rv->background->update = thread_timer_update;
   rv->spin = true;
   rv->handle_signals = true;
+  rv->owner = pthread_self();
 
 #if defined(HAVE_POLL_CALL)
   rv->handler.pfdsize = rv->fd_limit;
@@ -1021,7 +1022,7 @@ thread_cancel_read_or_write (struct thread *thread, short int state)
  * Cancel thread from scheduler.
  *
  * This function is *NOT* MT-safe. DO NOT call it from any other pthread except
- * the one which owns thread->master.
+ * the one which owns thread->master. You will crash.
  */
 void
 thread_cancel (struct thread *thread)
@@ -1030,8 +1031,10 @@ thread_cancel (struct thread *thread)
   struct pqueue *queue = NULL;
   struct thread **thread_array = NULL;
 
-  pthread_mutex_lock (&thread->master->mtx);
   pthread_mutex_lock (&thread->mtx);
+  pthread_mutex_lock (&thread->master->mtx);
+
+  assert (pthread_self() == thread->master->owner);
 
   switch (thread->type)
     {
@@ -1092,8 +1095,8 @@ thread_cancel (struct thread *thread)
   thread_add_unuse (thread->master, thread);
 
 done:
-  pthread_mutex_unlock (&thread->mtx);
   pthread_mutex_unlock (&thread->master->mtx);
+  pthread_mutex_unlock (&thread->mtx);
 }
 
 /* Delete all events which has argument value arg. */
index 218672c7bf9f08865d8927e5f9399bfb2e33397e..7e79eb38dcbaed4ef288c44332c9be79d6419291 100644 (file)
@@ -88,6 +88,7 @@ struct thread_master
   bool spin;
   bool handle_signals;
   pthread_mutex_t mtx;
+  pthread_t owner;
 };
 
 typedef unsigned char thread_type;