Project

General

Profile

Actions

Feature #20102

closed

Introduce `Fiber#resuming?`

Added by ioquatix (Samuel Williams) 11 months ago. Updated 8 months ago.

Status:
Closed
Target version:
-
[ruby-core:115952]

Description

There are some tricky edge cases when using Fibre#raise and Fiber#kill, e.g.

fiber = nil

killer = Fiber.new do
  fiber.raise("Stop")
end

fiber = Fiber.new do
  killer.resume
end

fiber.resume
# 4:in `raise': attempt to raise a resuming fiber (FiberError)
# 4:in `block in <main>'

Async has to deal with this edge case explicitly by rescuing the exception:

https://github.com/socketry/async/blob/ffd019d9c1d547926a28fe8f36bf7bfe91d8a168/lib/async/task.rb#L226-L233

I'd like to avoid doing that and instead just ask "Can I kill/raise on this fiber right now?" which is determined by whether the fiber itself can be resumed or transferred to.

To address this, I'd like to introduce Fiber#resuming?:

/*
 *  call-seq: fiber.resumed? -> true or false
 *
 *  Whether the fiber is currently resumed.
 */
VALUE
rb_fiber_resuming_p(VALUE fiber_value)
{
    struct rb_fiber_struct *fiber = fiber_ptr(fiber_value);

    if (FIBER_TERMINATED_P(fiber)) return RUBY_Qfalse;

    return RBOOL(fiber->resuming_fiber);
}

See the PR: https://github.com/ruby/ruby/pull/9382


Related issues 1 (0 open1 closed)

Related to Ruby master - Bug #20414: `Fiber#raise` should recurse to `resumed_fiber` rather than failing.Closedioquatix (Samuel Williams)Actions
Actions #1

Updated by ioquatix (Samuel Williams) 11 months ago

  • Description updated (diff)
Actions #2

Updated by jeremyevans0 (Jeremy Evans) 11 months ago

  • Tracker changed from Bug to Feature
  • Backport deleted (3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN)

Updated by Eregon (Benoit Daloze) 11 months ago

Could you make it raise FiberError if it's called on a Fiber of a different thread?
Because that's always racy (i.e. it might have changed by the time resuming? returns) so it seems wrong to query that for a Fiber belonging to another thread.

Updated by ioquatix (Samuel Williams) 11 months ago

@Eregon (Benoit Daloze) I appreciate your input. I don't mind doing that, but isn't that the same for all methods on Fiber? In other words, the GVL provides a bit of a safety net.

Should we apply this model to other methods? Maybe we need to define what methods can be called safely from one thread or another.

What about if a user has a mutex to control access, or the fiber/thread is not actually running at the time of the call?

I assume there is a lot of historical context/implementation where such behaviour is just racy but nothing is done to protect it.

In other words, I feel like the problem you are trying to address spans almost all of Ruby's mutable state... tricky.

Updated by Eregon (Benoit Daloze) 11 months ago

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

@Eregon (Benoit Daloze) I appreciate your input. I don't mind doing that, but isn't that the same for all methods on Fiber?

It is, and many methods on Fiber are already not allowed to be called for Fibers belonging to other threads (e.g. resume/transfer/storage/...).
Since we are adding a new method, we might as well encourage correct usage and discourage incorrect usage (+ it means the state for resuming does not need to become volatile which would be bad for performance).

In other words, the GVL provides a bit of a safety net.

It does not, the GVL could be released e.g. just after resuming? is done but before the caller gets the value and handle it.

Updated by matz (Yukihiro Matsumoto) 10 months ago

It appears to me that the method you want is to determine if an exception can legitimately be sent to the fiber. I am not rejecting the addition of such a method, but in that case, I think the name resuming? would be inappropriate. Any other name candidate?

Matz.

Actions #7

Updated by hsbt (Hiroshi SHIBATA) 8 months ago

  • Status changed from Open to Assigned

Updated by ioquatix (Samuel Williams) 8 months ago

  • Status changed from Assigned to Closed

I found a different way to solve this problem, which I think is better, so I'll open a new issue.

Actions #9

Updated by ioquatix (Samuel Williams) 8 months ago

  • Related to Bug #20414: `Fiber#raise` should recurse to `resumed_fiber` rather than failing. added
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0