From 4bf8fa83b7084040fbe12cc003f881ccf128c911 Mon Sep 17 00:00:00 2001
From: nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
Date: Fri, 15 Apr 2016 13:30:03 +0000
Subject: [PATCH] thread.c: defer setting name in initialize

* thread.c (rb_thread_setname): defer setting native thread name
  set in initialize until the native thread is created.
  [ruby-core:74963] [Bug #12290]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54600 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
---
 ChangeLog                | 10 ++++------
 test/ruby/test_thread.rb |  6 +++---
 thread.c                 | 28 +++++++++++++---------------
 thread_pthread.c         |  7 +++++--
 4 files changed, 25 insertions(+), 26 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 6045ee09a5..052628352e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,10 +1,8 @@
-Fri Apr 15 21:12:23 2016  Nobuyoshi Nakada  <nobu@ruby-lang.org>
+Fri Apr 15 22:30:01 2016  Nobuyoshi Nakada  <nobu@ruby-lang.org>
 
-	* thread.c (get_initialized_threadptr): extract ensuring that the
-	  thread is initialized.
-
-	* thread.c (rb_thread_setname): thread must be initialized to set
-	  the name.  [ruby-core:74963] [Bug #12290]
+	* thread.c (rb_thread_setname): defer setting native thread name
+	  set in initialize until the native thread is created.
+	  [ruby-core:74963] [Bug #12290]
 
 Fri Apr 15 20:27:16 2016  SHIBATA Hiroshi  <hsbt@ruby-lang.org>
 
diff --git a/test/ruby/test_thread.rb b/test/ruby/test_thread.rb
index 05bb536111..f13a962c9b 100644
--- a/test/ruby/test_thread.rb
+++ b/test/ruby/test_thread.rb
@@ -1099,9 +1099,9 @@ q.pop
     t.join
   end
 
-  def test_thread_setname_uninitialized
+  def test_thread_setname_in_initialize
     bug12290 = '[ruby-core:74963] [Bug #12290]'
-    c = Class.new(Thread) {def initialize() self.name = "foo" end}
-    assert_raise(ThreadError, bug12290) {c.new {}}
+    c = Class.new(Thread) {def initialize() self.name = "foo"; super; end}
+    assert_equal("foo", c.new {Thread.current.name}.value)
   end
 end
diff --git a/thread.c b/thread.c
index e8c7e606d8..ac31da5299 100644
--- a/thread.c
+++ b/thread.c
@@ -711,17 +711,7 @@ thread_create_core(VALUE thval, VALUE args, VALUE (*fn)(ANYARGS))
     return thval;
 }
 
-static rb_thread_t *
-get_initialized_threadptr(VALUE thread, VALUE klass)
-{
-    rb_thread_t *th;
-    GetThreadPtr(thread, th);
-    if (!th->first_args) {
-	rb_raise(rb_eThreadError, "uninitialized thread - check `%"PRIsVALUE"#initialize'",
-		 klass);
-    }
-    return th;
-}
+#define threadptr_initialized(th) ((th)->first_args != 0)
 
 /*
  * call-seq:
@@ -746,13 +736,18 @@ get_initialized_threadptr(VALUE thread, VALUE klass)
 static VALUE
 thread_s_new(int argc, VALUE *argv, VALUE klass)
 {
+    rb_thread_t *th;
     VALUE thread = rb_thread_alloc(klass);
 
     if (GET_VM()->main_thread->status == THREAD_KILLED)
 	rb_raise(rb_eThreadError, "can't alloc thread");
 
     rb_obj_call_init(thread, argc, argv);
-    get_initialized_threadptr(thread, klass);
+    GetThreadPtr(thread, th);
+    if (!threadptr_initialized(th)) {
+	rb_raise(rb_eThreadError, "uninitialized thread - check `%"PRIsVALUE"#initialize'",
+		 klass);
+    }
     return thread;
 }
 
@@ -2797,7 +2792,8 @@ rb_thread_setname(VALUE thread, VALUE name)
 #ifdef SET_ANOTHER_THREAD_NAME
     const char *s = "";
 #endif
-    rb_thread_t *th = get_initialized_threadptr(thread, RBASIC_CLASS(thread));
+    rb_thread_t *th;
+    GetThreadPtr(thread, th);
     if (!NIL_P(name)) {
 	rb_encoding *enc;
 	StringValueCStr(name);
@@ -2813,7 +2809,9 @@ rb_thread_setname(VALUE thread, VALUE name)
     }
     th->name = name;
 #if defined(SET_ANOTHER_THREAD_NAME)
-    SET_ANOTHER_THREAD_NAME(th->thread_id, s);
+    if (threadptr_initialized(th)) {
+	SET_ANOTHER_THREAD_NAME(th->thread_id, s);
+    }
 #endif
     return name;
 }
@@ -2836,7 +2834,7 @@ rb_thread_inspect(VALUE thread)
     GetThreadPtr(thread, th);
     status = thread_status_name(th);
     str = rb_sprintf("#<%"PRIsVALUE":%p", cname, (void *)thread);
-    if (RTEST(th->name)) {
+    if (!NIL_P(th->name)) {
 	rb_str_catf(str, "@%"PRIsVALUE, th->name);
     }
     if (!th->first_func && th->first_proc) {
diff --git a/thread_pthread.c b/thread_pthread.c
index 1fdf3f5431..0f62c6d603 100644
--- a/thread_pthread.c
+++ b/thread_pthread.c
@@ -1505,8 +1505,11 @@ native_set_thread_name(rb_thread_t *th)
 {
 #ifdef SET_CURRENT_THREAD_NAME
     if (!th->first_func && th->first_proc) {
-	VALUE loc = rb_proc_location(th->first_proc);
-	if (!NIL_P(loc)) {
+	VALUE loc;
+	if (!NIL_P(loc = th->name)) {
+	    SET_CURRENT_THREAD_NAME(RSTRING_PTR(loc));
+	}
+	else if (!NIL_P(loc = rb_proc_location(th->first_proc))) {
 	    const VALUE *ptr = RARRAY_CONST_PTR(loc); /* [ String, Fixnum ] */
 	    char *name, *p;
 	    char buf[16];