Hi Paul, > Your revised ConditionVariable#wait: > > def wait(mutex) > unlocked = false > begin > mutex.exclusive_unlock do > unlocked = true > @waiters.push(Thread.current) > Thread.stop > end > rescue # Timeout::Error > @waiters.delete Thread.current # Q: is Array#delete an atomic operation? > raise > ensure > mutex.lock if unlocked > end > end > > What happens if you get a timeout first inside the exclusive_unlock > block, then inside the rescue (before the delete occurs)? > > (I believe that this is a pretty rare race condition, but is still > possible). Wow, nice catch! Thanks - ! Hmm... Would that mean it's possible for ensure # -------> %exception here% mutex.lock if unlocked end potentially an exception firing once we're in the ensure block as well? Or is ensure implemented to have the properties of your no_raise style block, I wonder? Well, the reason I had proposed the timeout-safe wait, or wanted to implement it using timeout, is because I thought it would be easier than the signal-based timed_wait I had also implemented. I wrote what I believed to be a thread-safe (and hopefully exception safe) timed_wait using signals, to sidestep the "timeout" exception throwing issue. But it came out to a disconcerting 36 lines... 01: class ConditionVariable 02: 03: def timed_wait(mutex, timeout_secs) 04: waiter_th = Thread.current 05: alarm_th = nil 06: unlocked = false 07: begin 08: awake = false 09: 10: alarm_th = Thread.start do 11: sleep timeout_secs 12: Thread.exclusive do 13: unless awake 14: awake = true 15: @waiters.delete waiter_th 16: waiter_th.wakeup 17: end 18: end 19: end 20: 21: Thread.exclusive do 22: unless awake 23: mutex.exclusive_unlock do 24: unlocked = true 25: @waiters.push(Thread.current) 26: begin 27: Thread.stop 28: ensure 29: awake = true 30: end 31: end 32: end 33: end 34: ensure 35: mutex.lock if unlocked 36: alarm_th.kill if alarm_th and alarm_th.alive? 37: end 38: end 39: 40: end I say disconcerting because the code in thread.rb is so beautifully simple. (Although, as we have seen, it is not necessarily 100% well-protected, on the other hand.) But this routine above seemed more complicated than I'd like. [Note - I didn't care if it worked with timeout, since it doesn't use timeout.] . . . Wow your observation has really got me curious now: Can the exception raised by timeout occur anywhere in: - a rescue block? - an ensure block? That would seem to make it really hard to guard against... Thanks for your thoughts ! Regards, Bill