]> granicus.if.org Git - gc/commitdiff
Fix data race in last_stop_count access (suspend_handler_inner)
authorIvan Maidanski <ivmai@mail.ru>
Thu, 23 Nov 2017 17:15:54 +0000 (20:15 +0300)
committerIvan Maidanski <ivmai@mail.ru>
Mon, 18 Dec 2017 07:10:25 +0000 (10:10 +0300)
(Cherry-pick commit 3961ab98 from 'release-7_6' branch.)

* include/private/pthread_stop_world.h [!GC_OPENBSD_UTHREADS]
(thread_stop_info.last_stop_count): Do not define if NACL; change the
type from word to AO_t; add volatile qualifier; fix a typo in comment
("GC_stop_count").
* pthread_stop_world.c [!GC_OPENBSD_UTHREADS && !NACL]
(GC_suspend_handler_inner): Replace
me->stop_info.last_stop_count=my_stop_count with
AO_store_release(&me->stop_info.last_stop_count,my_stop_count).
* pthread_stop_world.c [!GC_OPENBSD_UTHREADS && !NACL]
(GC_suspend_all): Replace p->stop_info.last_stop_count with
AO_load(&p->stop_info.last_stop_count).

include/private/pthread_stop_world.h
pthread_stop_world.c

index 48374286722e1914fa3ae04fd814fe58d0f5707a..82e1031f77fbbe5ee46423a046e17c638627a5b5 100644 (file)
 #define GC_PTHREAD_STOP_WORLD_H
 
 struct thread_stop_info {
-#   ifndef GC_OPENBSD_UTHREADS
-      word last_stop_count;     /* GC_last_stop_count value when thread */
-                                /* last successfully handled a suspend  */
-                                /* signal.                              */
+#   if !defined(GC_OPENBSD_UTHREADS) && !defined(NACL)
+      volatile AO_t last_stop_count;
+                        /* The value of GC_stop_count when the thread   */
+                        /* last successfully handled a suspend signal.  */
 #   endif
 
     ptr_t stack_ptr;            /* Valid only when stopped.             */
index 2ab6cd702ad6cef405dcca42958062b7e3795dc4..e06215ecf969490ca07fbf208537207f9f6c85da 100644 (file)
@@ -279,7 +279,7 @@ STATIC void GC_suspend_handler_inner(ptr_t sig_arg,
   /* thread has been stopped.  Note that sem_post() is          */
   /* the only async-signal-safe primitive in LinuxThreads.      */
   sem_post(&GC_suspend_ack_sem);
-  me -> stop_info.last_stop_count = my_stop_count;
+  AO_store_release(&me->stop_info.last_stop_count, my_stop_count);
 
   /* Wait until that thread tells us to restart by sending      */
   /* this thread a GC_sig_thr_restart signal (should be masked  */
@@ -484,7 +484,8 @@ STATIC int GC_suspend_all(void)
             if (p -> flags & FINISHED) continue;
             if (p -> thread_blocked) /* Will wait */ continue;
 #           ifndef GC_OPENBSD_UTHREADS
-              if (p -> stop_info.last_stop_count == GC_stop_count) continue;
+              if (AO_load(&p->stop_info.last_stop_count) == GC_stop_count)
+                continue;
               n_live_threads++;
 #           endif
 #           ifdef DEBUG_THREADS