about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2009-10-10 15:57:12 -0700
committerEric Wong <normalperson@yhbt.net>2009-10-10 15:57:52 -0700
commit3b0bf229c40a9e460b71e751932481e66e90c26a (patch)
treea3aea677402856fb5f9e93f6ccc99323aab03e1c
parent5a5493fefb9048a7362e3bcb629cc363df529422 (diff)
downloadrainbows-3b0bf229c40a9e460b71e751932481e66e90c26a.tar.gz
We log thread destruction times now and also make a best-effort
to avoid race conditions on threads that just finished.
-rw-r--r--lib/rainbows/thread_spawn.rb23
1 files changed, 12 insertions, 11 deletions
diff --git a/lib/rainbows/thread_spawn.rb b/lib/rainbows/thread_spawn.rb
index 99647d5..0e023cd 100644
--- a/lib/rainbows/thread_spawn.rb
+++ b/lib/rainbows/thread_spawn.rb
@@ -37,9 +37,7 @@ module Rainbows
         end
 
         ret.first.each do |l|
-          while threads.list.size >= limit
-            nuke_old_thread(threads)
-          end
+          nuke_old_thread(threads, limit)
           c = begin
             l.accept_nonblock
           rescue Errno::EAGAIN, Errno::ECONNABORTED
@@ -56,15 +54,18 @@ module Rainbows
       join_spawned_threads(threads)
     end
 
-    def nuke_old_thread(threads)
-      threads.list.each do |thr|
-        next if (Time.now - (thr[:t] || next)) < timeout
-        thr.kill
-        logger.error "killed #{thr.inspect} for being too old"
-        return
+    def nuke_old_thread(threads, limit)
+      while (list = threads.list).size > limit
+        list.each do |thr|
+          thr.alive? or return # it _just_ died, we don't need it
+          next if (age = (Time.now - (thr[:t] || next))) < timeout
+          thr.kill # no-op if already dead
+          logger.error "killed #{thr.inspect} for being too old: #{age}"
+          return
+        end
+        # nothing to kill, yield to another thread
+        Thread.pass
       end
-      # nothing to kill, yield to another thread
-      Thread.pass
     end
 
     def join_spawned_threads(threads)