From: yuanyi zhang Date: 2007-07-04T01:41:54+09:00 Subject: Timeout doesn't work correctly under windows when executing complex regexp. To repeat the problem, just execute the below code(I've run it with ruby185 and 186, you may need increase the complexity of regexp if you own a high performance machine): require "rfuzz/session" include RFuzz c = HttpClient.new("www.ruby-lang.org", 80) r = c.get("/en/") p = r.http_body p.gsub!(/\r\n/, '') s = "
.*?
.*?
.*?
.*?" timeout(1) { p.gsub(Regexp.new(s)) { } } This snippet code will be executed more than 1 second under windows with my old hp notebook, and it won't raise any exception(but works fine under ubuntu6). I've traced the Ruby source, and I found it is because monitor thread(y thread in below code) won't get woken up: timeout.rb: def timeout(sec, exception=Error) return yield if sec == nil or sec.zero? raise ThreadError, "timeout within critical session" if Thread.critical begin x = Thread.current y = Thread.start { sleep sec x.raise exception, "execution expired" if x.alive? } yield sec # return true ensure y.kill if y and y.alive? end end The reason why Y thread won't be woken up is because rb_thread_tick in CHECK_INTS isn't decreased THREAD_TICK(500) times, so Y thread won't get scheduled until x finished: rubysig.h #define CHECK_INTS do {\ if (!(rb_prohibit_interrupt || rb_thread_critical)) {\ if (rb_thread_tick-- <= 0) {\ rb_thread_tick = THREAD_TICK;\ rb_thread_schedule();\ }\ }\ if (rb_trap_pending) rb_trap_exec();\ } while (0) So, in fact, this is a thread scheduler problem. I've submitted a Bug trace on rubyforge, you can find it at: http://rubyforge.org/tracker/?func=detail&aid=11980&group_id=426&atid=1698 I hope I understand correctly and the above analytics can give you a little help. BR. Yuanyi Zhang