[前][次][番号順一覧][スレッド一覧]

ruby-changes:51888

From: normal <ko1@a...>
Date: Sun, 29 Jul 2018 19:15:17 +0900 (JST)
Subject: [ruby-changes:51888] normal:r64102 (trunk): thread_pthread.c: clear altstacks in thread cache at GVL destruction

normal	2018-07-29 19:15:11 +0900 (Sun, 29 Jul 2018)

  New Revision: 64102

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=64102

  Log:
    thread_pthread.c: clear altstacks in thread cache at GVL destruction
    
    Otherwise, an altstack may live past ObjectSpace destruction
    and xfree-ing the altstack will segfault.
    
    [ruby-core:85621] [Feature #14487]

  Modified files:
    trunk/thread_pthread.c
    trunk/vm_core.h
Index: thread_pthread.c
===================================================================
--- thread_pthread.c	(revision 64101)
+++ thread_pthread.c	(revision 64102)
@@ -46,6 +46,7 @@ void rb_native_cond_wait(rb_nativethread https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L46
 void rb_native_cond_initialize(rb_nativethread_cond_t *cond);
 void rb_native_cond_destroy(rb_nativethread_cond_t *cond);
 static void rb_thread_wakeup_timer_thread_low(void);
+static void clear_thread_cache_altstack(void);
 
 #define TIMER_THREAD_MASK    (1)
 #define TIMER_THREAD_SLEEPY  (2|TIMER_THREAD_MASK)
@@ -66,6 +67,12 @@ static struct { https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L67
 } timer_thread;
 #define TIMER_THREAD_CREATED_P() (timer_thread.created != 0)
 
+#ifdef HAVE_SCHED_YIELD
+#define native_thread_yield() (void)sched_yield()
+#else
+#define native_thread_yield() ((void)0)
+#endif
+
 #if defined(HAVE_PTHREAD_CONDATTR_SETCLOCK) && \
     defined(CLOCK_REALTIME) && defined(CLOCK_MONOTONIC) && \
     defined(HAVE_CLOCK_GETTIME)
@@ -182,6 +189,7 @@ gvl_destroy(rb_vm_t *vm) https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L189
     rb_native_cond_destroy(&vm->gvl.switch_cond);
     rb_native_cond_destroy(&vm->gvl.cond);
     rb_native_mutex_destroy(&vm->gvl.lock);
+    clear_thread_cache_altstack();
 }
 
 #if defined(HAVE_WORKING_FORK)
@@ -367,11 +375,6 @@ native_cond_timeout(rb_nativethread_cond https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L375
 
 #define native_cleanup_push pthread_cleanup_push
 #define native_cleanup_pop  pthread_cleanup_pop
-#ifdef HAVE_SCHED_YIELD
-#define native_thread_yield() (void)sched_yield()
-#else
-#define native_thread_yield() ((void)0)
-#endif
 
 #if defined(SIGVTALRM) && !defined(__CYGWIN__)
 #define USE_UBF_LIST 1
@@ -452,7 +455,7 @@ native_thread_destroy(rb_thread_t *th) https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L455
 }
 
 #if USE_THREAD_CACHE
-static rb_thread_t *register_cached_thread_and_wait(void);
+static rb_thread_t *register_cached_thread_and_wait(void *);
 #endif
 
 #if defined HAVE_PTHREAD_GETATTR_NP || defined HAVE_PTHREAD_ATTR_GET_NP
@@ -855,14 +858,13 @@ thread_start_func_1(void *th_ptr) https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L858
 #endif
     }
 #if USE_THREAD_CACHE
-    if (1) {
-	/* cache thread */
-	if ((th = register_cached_thread_and_wait()) != 0) {
-	    goto thread_start;
-	}
+    /* cache thread */
+    if ((th = register_cached_thread_and_wait(RB_ALTSTACK(altstack))) != 0) {
+        goto thread_start;
     }
-#endif
+#else
     RB_ALTSTACK_FREE(altstack);
+#endif
     return 0;
 }
 
@@ -870,6 +872,7 @@ struct cached_thread_entry { https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L872
     rb_nativethread_cond_t cond;
     rb_nativethread_id_t thread_id;
     rb_thread_t *th;
+    void *altstack;
     struct list_node node;
 };
 
@@ -896,12 +899,13 @@ thread_cache_reset(void) https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L899
 #endif
 
 static rb_thread_t *
-register_cached_thread_and_wait(void)
+register_cached_thread_and_wait(void *altstack)
 {
     struct timespec end = { THREAD_CACHE_TIME, 0 };
     struct cached_thread_entry entry;
 
     rb_native_cond_initialize(&entry.cond);
+    entry.altstack = altstack;
     entry.th = NULL;
     entry.thread_id = pthread_self();
     end = native_cond_timeout(&entry.cond, end);
@@ -919,6 +923,9 @@ register_cached_thread_and_wait(void) https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L923
     rb_native_mutex_unlock(&thread_cache_lock);
 
     rb_native_cond_destroy(&entry.cond);
+    if (!entry.th) {
+        RB_ALTSTACK_FREE(entry.altstack);
+    }
 
     return entry.th;
 }
@@ -949,6 +956,22 @@ use_cached_thread(rb_thread_t *th) https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L956
     return 0;
 }
 
+static void
+clear_thread_cache_altstack(void)
+{
+#if USE_THREAD_CACHE
+    struct cached_thread_entry *entry;
+
+    rb_native_mutex_lock(&thread_cache_lock);
+    list_for_each(&cached_thread_head, entry, node) {
+        void MAYBE_UNUSED(*altstack) = entry->altstack;
+        entry->altstack = 0;
+        RB_ALTSTACK_FREE(altstack);
+    }
+    rb_native_mutex_unlock(&thread_cache_lock);
+#endif
+}
+
 static int
 native_thread_create(rb_thread_t *th)
 {
Index: vm_core.h
===================================================================
--- vm_core.h	(revision 64101)
+++ vm_core.h	(revision 64102)
@@ -123,9 +123,11 @@ https://github.com/ruby/ruby/blob/trunk/vm_core.h#L123
 void *rb_register_sigaltstack(void);
 #  define RB_ALTSTACK_INIT(var) var = rb_register_sigaltstack()
 #  define RB_ALTSTACK_FREE(var) xfree(var)
+#  define RB_ALTSTACK(var)  var
 #else /* noop */
 #  define RB_ALTSTACK_INIT(var)
 #  define RB_ALTSTACK_FREE(var)
+#  define RB_ALTSTACK(var) (0)
 #endif
 
 /*****************/

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]