Project

General

Profile

Bug #4285

Updated by ko1 (Koichi Sasada) over 8 years ago

=begin 
  
  This issue was discovered during [Bug#4266] discussion. 
  Current timeout is racy. 
 
  Now, timeout module has following code. 
  ------------------------------------------------------------------------------- 
    def timeout() 
      begin 
        x = Thread.current 
        y = Thread.start { 
          begin 
            sleep sec 
          rescue => e 
            x.raise e 
          else 
            x.raise exception, "execution expired" if x.alive? 
          end 
        } 
        return yield(sec) 
      rescue exception => e 
        raise Error, e.message, e.backtrace 
      ensure 
        if y and y.alive? 
          y.kill 
          y.join # make sure y is dead. 
        end 
      end 
    end 
  --------------------------------------------------------------- 
 
  Unfortunatelly,  
 
     y = Thread.start {} 
 
  is not an atomic operation. Then, A following race can occur. 
 
 
    CPU0(thread x)                       CPU1(thread y)           remark 
  --------------------------------------------------------------------------- 
    enter begin block 
    [thread construct]                                          but no assign y yet 
                                       sleep sec 
                                       wakeup from sleep 
                                       x.raise 
    if y                                                        return false. (see above) 
 
 
  Therefore, CPU0 don't call y.join and leak y's thread resource. C# have solved 
  this two-step-construction vs asynchrounous exception race by RAII. 
  (Plus, C#'s finally block is async exception safe automatically) 
 
  But unfortunately, Ruby don't have such language feature. So, We can't write 
  async-exception-safe code. One of solution is to move timeout module from ruby code 
  into c code as JRuby does. But I don't think timeout is only asynchrounos exception user. 
  we also have Interrupt class (for Ctrl-C) and I think we need to allow to write async  
  exception safe code by ruby. 
 
  So, My proposal is, 
   o for 1.9.x 
       => Reimplement timeout.rb by C (as JRuby) 
 
   o for 2.0 
       => Aim new feature for writing async exception safe code. 
 
 
  Or, Am I missing something? 
 
 =end 
 

Back