Issue #10231 has been updated by Eric Wong.


 I haven't checked the inits.c ordering change closely, but
 make check and test-rubyspec passes:
 
 diff --git a/inits.c b/inits.c
 index fe0aade..da8cfb1 100644
 --- a/inits.c
 +++ b/inits.c
 @@ -46,7 +46,6 @@ rb_call_inits(void)
      CALL(Time);
      CALL(Random);
      CALL(signal);
 -    CALL(process);
      CALL(load);
      CALL(Proc);
      CALL(Binding);
 @@ -56,6 +55,7 @@ rb_call_inits(void)
      CALL(VM);
      CALL(ISeq);
      CALL(Thread);
 +    CALL(process);
      CALL(Cont);
      CALL(Rational);
      CALL(Complex);
 diff --git a/process.c b/process.c
 index 8bb52f7..5bf59ac 100644
 --- a/process.c
 +++ b/process.c
 @@ -1007,6 +1007,8 @@ proc_waitall(void)
      return result;
  }
  
 +static VALUE rb_cWaiter;
 +
  static inline ID
  id_pid(void)
  {
 @@ -1038,7 +1040,7 @@ rb_detach_process(rb_pid_t pid)
  {
      VALUE watcher = rb_thread_create(detach_process_watcher, (void*)(VALUE)pid);
      rb_thread_local_aset(watcher, id_pid(), PIDT2NUM(pid));
 -    rb_define_singleton_method(watcher, "pid", detach_process_pid, 0);
 +    RBASIC_SET_CLASS(watcher, rb_cWaiter);
      return watcher;
  }
  
 @@ -7516,6 +7518,10 @@ Init_process(void)
      rb_define_module_function(rb_mProcess, "waitall", proc_waitall, 0);
      rb_define_module_function(rb_mProcess, "detach", proc_detach, 1);
  
 +    rb_cWaiter = rb_define_class_under(rb_mProcess, "Waiter", rb_cThread);
 +    rb_undef_method(CLASS_OF(rb_cWaiter), "new");
 +    rb_define_method(rb_cWaiter, "pid", detach_process_pid, 0);
 +
      rb_cProcessStatus = rb_define_class_under(rb_mProcess, "Status", rb_cObject);
      rb_undef_method(CLASS_OF(rb_cProcessStatus), "new");
  
 diff --git a/test/ruby/test_process.rb b/test/ruby/test_process.rb
 index 608d663..a3fa36e 100644
 --- a/test/ruby/test_process.rb
 +++ b/test/ruby/test_process.rb
 @@ -1965,4 +1965,10 @@ EOS
        runner.close
      end
    end if defined?(fork)
 +
 +  def test_process_detach
 +    pid = fork {}
 +    th = Process.detach(pid)
 +    assert_equal pid, th.pid
 +  end if defined?(fork)
  end
 
 -- 
 EW

----------------------------------------
Bug #10231: Process.detach(pid) defines new singleton classes every call
https://bugs.ruby-lang.org/issues/10231#change-48854

* Author: Charles Nutter
* Status: Open
* Priority: Normal
* Assignee: 
* Category: 
* Target version: 
* ruby -v: Any version with Process.detach
* Backport: 2.0.0: UNKNOWN, 2.1: UNKNOWN
----------------------------------------
The logic for Process.detach(pid) adds a singleton "pid" method to the thread it returns for every call. This is bad for method caches (MRI still flushes them all for this, I believe) and memory churn (singleton classes are not small).

The offending line of code is here: https://github.com/ruby/ruby/blob/trunk/process.c#L1041

I would suggest that Process.detach should return a subclass of Thread that has the pid method defined ahead of time.

It also stores the value in thread local storage, rather than as an instance variable. I'm not sure why.



-- 
https://bugs.ruby-lang.org/