On Fri, 2 Mar 2007, Eric Hodel wrote: > On Mar 1, 2007, at 07:12, Avdi Grimm wrote: >> On 3/1/07, Tomas Pospisek <tpo2 / sourcepole.ch> wrote: >>> However, this applies in exactly the same way to libc-select as well and >>> thus replacing the select/gettimeofday mechanism by libc-sleep should >>> at least work no worse. Objections? >> >> My first reaction was: good god, the scheduler uses wallclock time?! >> Speaking as someone who works on realtime systems (and thus has to >> think about scheduler implementation often), this is never a good >> idea. I don't know the background for Ruby's scheduler design, but >> normally I'd regard a scheduler which uses wallclock time as just >> plain *broken*. I'm heartily in favor of changing it to something >> which isn't dependent on the clock. > > The Ruby thread scheduler uses setitimer(2) and select(2). It depends on the > wall-clock for implementing features defined in terms of the wall-clock > (Kernel#sleep and Thread#join). You need to add Timeout#timeout to this. But: $ ri Kernel#sleep Suspends the current thread for _duration_ seconds (which may be any number, including a +Float+ with fractional seconds). Returns the actual number of seconds slept (rounded), which may be less than that asked for if another thread calls +Thread#run+. Zero arguments causes +sleep+ to sleep forever. No reference to wall-clock in there. What do you mean by "defined in terms of the wall-clock"? >> That "indeterminate amount" referenced above is simply the price you >> pay for running in userspace ion a modern multitasking OS. Yes, >> system activity could delay the return. That's what multitasking >> means: you don't get to choose when you get the CPU. In practice, if >> applications are experiencing unacceptable latency in OS scheduling >> then 1) your gettimeofday()-based implementation is going to be >> delayed right along with everything else; and 2) you have bigger >> problems, because your system is overloaded. > > Kernel#sleep behaves differently in Ruby programs using threads. If you > sleep in a thread you end up context switching to other threads instead of > calling sleep(3). > > Since you aren't using sleep(3) in threaded mode, Ruby instead uses > gettimeofday(2) to implement Kernel#sleep for the calling thread (has this > thread slept its N seconds?), so you may sleep longer than you expect. > > The other place gettimeofday(2) is used is Thread#join's timeout, for similar > reason. The problem is that when you set system time into the past by a month, then your thread will also sleep for a month and not, as you probably expected, only a few seconds. Which is actually the hint for the solution... to be followed. *t -- ----------------------------------------------------------- Tomas Pospisek http://sourcepole.com - Linux & Open Source Solutions -----------------------------------------------------------