Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Fiber.current for current execution context. Fixes #501. #502

Closed
wants to merge 2 commits into from

Conversation

ioquatix
Copy link

No description provided.

@ioquatix
Copy link
Author

@eregon wdyt?

@ioquatix
Copy link
Author

I'm not sure what the best option is to resolve the failure - do we add fiber to the list of exceptions?

Copy link
Member

@pirj pirj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're dropping old rubies (< 2.3) in RSpec 4.
What are your primary targets? Do you still plan to support old rubies with pre-4.0 RSpec?

Does it make sense for RSpec to remove ReentrantMutex and use Monitor?
Or is it the case that Monitor has that same bug with Fiber.yield inside synchronize, and we'd better keep ReentrantMutex with what we'll end up doing in this PR that would work with any Ruby version? And the plan is to keep it until we drop support for Ruby 3.0?

@@ -1,3 +1,5 @@
require 'fiber'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I foresee that @JonRowe would say that requiring a dependency from stdlib is something that we try to avoid at all costs.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we don't require things that developers need to require because it causes weird failures for developers. (e.g. RSpec will pass because we require it but it won't work in dev/production).

Comment on lines +33 to +34
@mutex.lock if @owner != Fiber.current
@owner = Fiber.current
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WDYT of

def current
  defined?(Fiber.current) ? Fiber.current : Thread.current
end

and using it?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's broken.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please elaborate?

Copy link
Contributor

@eregon eregon Apr 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whenever some file would require 'fiber' the behavior and what's stored here would switch and it'd be a total mess.
Also Thread.current is not good enough if there is any non-root Fiber (any Fiber.new).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some file would require 'fiber' the behavior and what's stored here would switch and it'd be a total mess

For sure. I hope they don't do it dynamically when there are existing fibers and reentrant mutexes in action. Otherwise - do you see any issue?

Ok, let's put it another way. I couldn't find any mention of Fiber in stdlib docs. Core docs claim that in order to user current/transfer/alive? one has to require 'fiber'.
Unlike it is with require 'rubygems' or require 'date', require 'set' etc no constants are loaded, and it's not a problem if we load it from RSpec.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this not break in a more typical threaded solution? E.g. JRuby

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hope they don't do it dynamically when there are existing fibers and reentrant mutexes in action.

I don't think it's advisable to take that risk/assumption, and anyway AFAIK there is no need.

@pirj
Copy link
Member

pirj commented Apr 26, 2021

the best option is to resolve the failure

My guess is that it compares loaded features to a clean process. It's a defensive measure to avoid loading anything explicitly, including 'fiber'.

@ioquatix
Copy link
Author

I would suggest that if monitor worked, you should use it, but it's broken by the same bug. Ideally we fix this in 3.0.2

@eregon
Copy link
Contributor

eregon commented Apr 26, 2021

The change looks good to me.

Unfortunately there is no way to get Fiber.current without require 'fiber' in Ruby code (maybe we should change that in Ruby). fiber is not a default gem or anything you could replace, so requiring fiber seems fairly safe to me.
It does have the downside that a gem might appear to work when running specs, but not when used outside of specs, e.g., if it uses Fiber.current, Fiber#alive? or Fiber#transfer (fairly unlikely I'd say).
That's a general issue though, any test dependency might require stdlibs, and IMHO there should be at least one integration test using a subprocess to make sure this isn't an issue while loading the gem's files.

Using monitor seems best when available, but that's also a stdlib.
monitor is also not a default gem, since it is a dependency of RubyGems.
Because RubyGems already requires it, I think there is little problems to require it & use it in RSpec.

@pirj
Copy link
Member

pirj commented Apr 26, 2021

@eregon We don't require Rubygems as well, and even explicitly avoid loading them on CI.
Rails, e.g. refers to Rubygems in their to securely compare gem versions, and don't explicitly require it that would break if Rails is run with Rubygems disabled with rubyopt. We deliberately don't require anything from stdlib unless absolutely necessary to prevent such breakages.

@eregon
Copy link
Contributor

eregon commented Apr 26, 2021

I think one way to avoid needing any stdlib here is to use Mutex#owned? and remove the @owner field entirely.
Then neither Thread.current or Fiber.current would be used, and it'd be correct.

@pirj
Copy link
Member

pirj commented Apr 26, 2021

@eregon Amazing, thank you!
@ioquatix Would #owned? fix your failing case?

@ioquatix
Copy link
Author

I can try it out this week and report back

@eregon
Copy link
Contributor

eregon commented Apr 27, 2021

I made a PR using Mutex#owned?: #503

@ioquatix
Copy link
Author

I defer to @eregon thanks for your help here.

@ioquatix ioquatix closed this Apr 27, 2021
@ioquatix ioquatix deleted the patch-1 branch April 27, 2021 22:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants