[#9445] thread.rb — m_seki@...

18 messages 2000/03/16
[#9446] Re: thread.rb — matz@... (Yukihiro Matsumoto) 2000/03/17

[#9460] Re: thread.rb — m_seki@... 2000/03/21

[#9462] Re: thread.rb — matz@... (Yukihiro Matsumoto) 2000/03/21

まつもと ゆきひろです

[#11281] Re: thread.rb — Masatoshi SEKI <m_seki@...> 2000/10/22

[#9498] timeout しない timeout — ARIMA Yasuhiro <fit0298@...>

有馬です。

20 messages 2000/03/26
[#9506] Re: timeout しない timeout — matz@... (Yukihiro Matsumoto) 2000/03/27

まつもと ゆきひろです

[#9509] Re: timeout しない timeout — gotoken@... (GOTO Kentaro) 2000/03/27

In message "[ruby-dev:9506] Re: timeout しない timeout"

[ruby-dev:9445] thread.rb

From: m_seki@...
Date: 2000-03-16 00:05:16 UTC
List: ruby-dev #9445
咳といいます。

1.4.3 のthread.rb を読んでました。

thread.rb に入っているスレッドの同期メカニズムなんですが、
(Queue, Mutex等)資源待ちのスレッドがだれかに exit された場合、
run や wakeup するときに失敗してしまうと思います。

	require 'thread'

	def reader(q)
	  Thread.new do
	    q.pop
	  end
	end

	q = Queue.new
	t1 = reader(q)
	t2 = reader(q)

	t1.exit		# まとめてにkillされたりTimeoutでkillされたり‥

	q.push('hello')
	→ ThreadError


ThreadGroupなどでまとめてkillできるようになると、
こういう局面がよくありそうな気がするのですが問題に
ならないでしょうか?


またMutex, Queueでは@waitingの先頭のスレッドだけを run/wakeup 
しますが、@waiting中のすべてのスレッドをwakeupしないとまずい
局面がないですか。
起こされたスレッドが資源を獲得する前にこけちゃうとか。
# 考えなくていいのかな。よくわかんない。


以下 wakeup/run で ThreadError を rescue するパッチです。
QueueとMutexは試しましたがSizedQueue、状態変数はやってません。
# あっているか不安。


*** /usr/local/lib/ruby/1.4/thread.rb	Mon Sep 13 13:32:35 1999
--- thread.rb	Thu Mar 16 08:45:12 2000
***************
*** 63,72 ****
    def unlock
      return unless @locked
      Thread.critical = true
-     t = @waiting.shift
      @locked = false
      Thread.critical = false
-     t.run if t
      self
    end
  
--- 63,76 ----
    def unlock
      return unless @locked
      Thread.critical = true
      @locked = false
+     begin
+       t = @waiting.shift
+       t.wakeup if t
+     rescue ThreadError
+       retry
+     end
      Thread.critical = false
      self
    end
  
***************
*** 82,90 ****
    def exclusive_unlock
      return unless @locked
      Thread.exclusive do
-       t = @waiting.shift
        @locked = false
!       t.wakeup if t
        yield
      end
      self
--- 86,98 ----
    def exclusive_unlock
      return unless @locked
      Thread.exclusive do
        @locked = false
!       begin
! 	t = @waiting.shift
! 	t.wakeup if t
!       rescue ThreadError
! 	retry
!       end
        yield
      end
      self
***************
*** 105,112 ****
    end
    
    def signal
!     t = @waiters.shift
!     t.run if t
    end
      
    def broadcast
--- 113,124 ----
    end
    
    def signal
!     begin
!       t = @waiters.shift
!       t.run if t
!     rescue ThreadError
!       retry
!     end
    end
      
    def broadcast
***************
*** 116,122 ****
        @waiters.clear
      end
      for t in waiters0
!       t.run
      end
    end
  end
--- 128,137 ----
        @waiters.clear
      end
      for t in waiters0
!       begin
! 	t.run
!       rescue ThreadError
!       end
      end
    end
  end
***************
*** 133,141 ****
    def push(obj)
      Thread.critical = true
      @que.push obj
!     t = @waiting.shift
      Thread.critical = false
-     t.run if t
    end
    alias enq push
  
--- 148,160 ----
    def push(obj)
      Thread.critical = true
      @que.push obj
!     begin
!       t = @waiting.shift
!       t.wakeup if t
!     rescue ThreadError
!       retry
!     end
      Thread.critical = false
    end
    alias enq push
  
***************
*** 201,208 ****
        @max = max
        Thread.critical = false
        diff.times do
! 	t = @queue_wait.shift
! 	t.run if t
        end
      end
      max
--- 220,231 ----
        @max = max
        Thread.critical = false
        diff.times do
! 	begin
! 	  t = @queue_wait.shift
! 	  t.run if t
! 	rescue ThreadError
! 	  retry
! 	end
        end
      end
      max
***************
*** 221,228 ****
    def pop(*args)
      Thread.critical = true
      if @que.length < @max
!       t = @queue_wait.shift
!       t.run if t
      end
      super
    end
--- 244,255 ----
    def pop(*args)
      Thread.critical = true
      if @que.length < @max
!       begin
! 	t = @queue_wait.shift
! 	t.run if t
!       rescue ThreadError
! 	retry
!       end
      end
      super
    end

In This Thread

Prev Next