Project

General

Profile

Actions

Feature #17470

closed

Introduce non-blocking `Timeout.timeout`

Added by ioquatix (Samuel Williams) about 2 years ago. Updated almost 2 years ago.

Status:
Closed
Priority:
Normal
Target version:
-
[ruby-core:101704]

Description

In this bug report, user complained that Timeout.timeout does not work correctly with scheduler: https://github.com/socketry/async-io/issues/43

We should introduce non-blocking timeout.

I propose the following:

rb_fiber_scheduler_with_timeout(VALUE scheduler, VALUE timeout, VALUE block)

We can directly modify Timeout.timeout to invoke this hook.


Related issues 1 (1 open0 closed)

Related to Ruby master - Feature #17363: TimeoutsAssignedko1 (Koichi Sasada)Actions

Updated by Eregon (Benoit Daloze) about 2 years ago

How would that work, what would be a sample implementation of the hook?
Timeout.timeout must be able to interrupt non-IO operations as well.

Updated by ioquatix (Samuel Williams) about 2 years ago

Timeout.timeout must be able to interrupt non-IO operations as well.

Actually, that's not necessarily true, even for the current implementation, see getaddrinfo for example.

Updated by jsc (Justin Collins) about 2 years ago

It appears that Timeout.timeout does not work when a Fiber scheduler is set, regardless of the implementation, even when Fibers are not explicitly in use.

Simple example using the sample scheduler:

require 'timeout'
require 'fiber'
require_relative 'scheduler'

scheduler = Scheduler.new
Fiber.set_scheduler scheduler

Timeout.timeout 1 do
  puts "hello"
end

This code will print "hello" then hang.

Updated by Eregon (Benoit Daloze) about 2 years ago

ioquatix (Samuel Williams) wrote in #note-2:

Actually, that's not necessarily true, even for the current implementation, see getaddrinfo for example.

You're completely evading my question :p
Could you answer it please?

That's one of the very rare cases, maybe even the only case in core methods that cannot be interrupted by Thread#raise.

Is the idea to simply give up on interrupting anything that's not handled by the scheduler if there is a Fiber.scheduler, or something better?
That seems too incompatible to me.
I think a new API to interrupt only scheduler things might make more sense (related to #17363).

Actions #5

Updated by Eregon (Benoit Daloze) about 2 years ago

Actions #6

Updated by jeremyevans0 (Jeremy Evans) almost 2 years ago

  • Tracker changed from Bug to Feature
  • Backport deleted (2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN)

Updated by ioquatix (Samuel Williams) almost 2 years ago

@Eregon (Benoit Daloze) without preemptive scheduling it won't be possible. There are other cases where the GVL is not released, e.g. the sqlite3 gem. In the case of the scheduler, Timeout.timeout is completely broken, so this is an improvement any way you cut it.

Updated by ioquatix (Samuel Williams) almost 2 years ago

@jsc (Justin Collins) I tried your example but it seems to work fine?

  MESSAGE = "Hello World"

  def test_timeout_on_main_fiber
    message = nil

    thread = Thread.new do
      scheduler = Scheduler.new
      Fiber.set_scheduler scheduler

      Timeout.timeout(1) do
        message = MESSAGE
      end
    end

    thread.join

    assert_equal MESSAGE, message
  end

Updated by ioquatix (Samuel Williams) almost 2 years ago

  • Status changed from Open to Closed
  • Assignee set to ioquatix (Samuel Williams)
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0