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

Lock on the current Fiber rather than current Thread #1284

Merged
merged 1 commit into from
Dec 17, 2022

Conversation

casperisfine
Copy link
Contributor

@casperisfine casperisfine commented Nov 21, 2022

Applications using fiber are able to do concurrent queries from the same thread.

Ref: rails/rails#46519 (comment)

NB: I'm not sure when rb_fiber_current() was introduced, so I'm waiting for CI to see.

@casperisfine
Copy link
Contributor Author

NB: I'm not sure when rb_fiber_current() was introduced, so I'm waiting for CI to see.

Looks like 2.1 has it, no idea for 2.0, but it's not ran on CI.

@casperisfine
Copy link
Contributor Author

no idea for 2.0

I checked, it has it, I'll remove the conditional.

@casperisfine casperisfine force-pushed the active-fiber branch 2 times, most recently from 6a9b3f3 to ba0b516 Compare November 21, 2022 09:32
@ioquatix
Copy link

This looks reasonable to me but would it be better to just use a mutex?

@sodabrew
Copy link
Collaborator

This is great! I think it may solve quite a few mystery reports of out of sequence commands despite not crossing threads.

Re: mutex, the gem assumes the client connection pool is handling this. Is that assumption worth revisiting?

@@ -2,6 +2,8 @@
require 'mysql2'
require 'timeout'
require 'yaml'
require 'fiber'
Copy link
Collaborator

@sodabrew sodabrew Nov 21, 2022

Choose a reason for hiding this comment

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

It sounds like there's no need to raise the minimum Ruby for this import, but I definitely would be comfortable raising the baseline for this PR if needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah I don't think it's needed.

IMHO 2.0 is really really old and people who are still on it don't deserve time. I now require 2.5 across all my projects. But that is totally independent of this PR.

ext/mysql2/client.h Outdated Show resolved Hide resolved
@ioquatix
Copy link

ioquatix commented Nov 21, 2022

Well, it sounds like what you basically have is a poor version of a mutex, since you are tracking a critical section with an active_whatever. If you just used Mutex for this, you wouldn't have this PR, because it would already just work. You can bail on locking a mutex by checking Mutex#locked? or if you want reentrancy, Mutex#owned? (the current execution context has locked it). This is more compatible since not all platforms currently have fiber-level mutex (but there is nothing wrong with the current PR).

@casperisfine
Copy link
Contributor Author

but would it be better to just use a mutex?

This is essentially the same thing, Ruby's mutex is also just a struct with the current fiber store in. This is essentially an inlined mutex.

We could take it out and use a Mutex on the Ruby side, but that would reduce perf a bit, and expose us to bugs with interrupts and such (we'd need to use Thead.handle_interrupt).

So I'd say no.

I think it may solve quite a few mystery reports of out of sequence commands despite not crossing threads.

Actually I doubt so. Short of people using a fiber scheduler and some weird enumerator usages this shouldn't change much.

However I do think the current protection has a few holes, in several cases we release the lock too early which I think open some small race-condidtion windows that can cause segfaults.

I started working on improving this a bit, but haven't finished yet, I'll try to get back on it: Shopify@13b38da

Re: mutex, the gem assumes the client connection pool is handling this. Is that assumption worth revisiting?

IMO no. You shouldn't use the connection concurrently, you should use a pool as you say. This check is just here so that if you mess it up we raise and error instead of segfaulting.

Applications using fiber are able to do concurrent queries
from the same thread.
@casperisfine
Copy link
Contributor Author

@sodabrew any changes required for this PR to be mergeable?

@sodabrew sodabrew merged commit 1ac6978 into brianmario:master Dec 17, 2022
@ioquatix
Copy link

Nice work team.

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.

5 participants