Saravanan
Saravanan

Reputation: 509

Ruby Timeout.timeout does not timeout in x secs

Below code

Timeout.timeout(2) do
  i = 0
  while(true)
    i = i + 1
    p "test #{i}"
  end
end

does not timeout in 2 secs. whereas below similar code timeout in 2 seconds

Timeout.timeout(2) do
  i = 0
  while(true)
    i = i + 1
    # p "test #{i}"
  end
end

What is the underlying difference? Please help.

Upvotes: 0

Views: 859

Answers (1)

deibele1
deibele1

Reputation: 51

I don't know exactly what's going on here and I suspect somebody who understands the underlying C code would be the one to give a complete answer. I have an inkling. The Matz Ruby Interpreter (MRI) has a global thread lock which means only one thread can actually run at any given time. The way threading works is when one thread is waiting on a resource it sleeps and this gives another thread opportunity to run.

Timeout creates a second thread that will sleep for 2 seconds then raise an exception on the current thread enforcing the timeout. We are guaranteed this thread will not run before 2 seconds but not guaranteed exactly when it will run after 2 seconds but usually a few milliseconds or so with some exceptions.

The function p is unique in that it writes directly to std.out. This is where a C programmer may be helpful but it appears to me that its starving the other thread of resources possibly because to throw an exception the second thread needs to own std.out.

p and pp both cause this problem whereas puts does not.

In support of the resource starvation theory the following code works

Timeout.timeout(2) do
  i = 0
  while(true)
    i = i + 1
    p "testing timeout #{i}"
    sleep 0.001
  end
end

Upvotes: 1

Related Questions