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

Automatic Fork Safety #814

Merged
merged 1 commit into from Feb 2, 2023
Merged

Automatic Fork Safety #814

merged 1 commit into from Feb 2, 2023

Conversation

casperisfine
Copy link

Forking servers are a popular deployment method in Ruby. One big footgun is that uppon fork, all file descriptors are inherited, so if you create some FDs before fork and hold on them you may end up with the same connection being used across many process creating havoc.

As such it's a good idea for libraries that do keep persistent connections do check the PID before re-using them.

The alternative is for libraries to provide some kind of callback that the application has to call before fork, but that's easilly missed by users and the PID check is very cheap.

Forking servers are a popular deployment method in Ruby.
One big footgun is that uppon fork, all file descriptors
are inherited, so if you create some FDs before fork and hold on them
you may end up with the same connection being used across many process
creating havoc.

As such it's a good idea for libraries that do keep persistent
connections do check the PID before re-using them.

The alternative is for libraries to provide some kind of callback that
the application has to call before fork, but that's easilly missed
by users and the PID check is very cheap.
@geemus
Copy link
Contributor

geemus commented Feb 2, 2023

@byroot Thanks. I think the code looks good and it makes sense, my main concern would be around performance since it adds those regular PID lookups to pretty much everything. I was trying to give myself broader context and saw your comments about performance concerns also here: https://bugs.ruby-lang.org/issues/17795. Does that remain a concern for something like this? Should we consider, for instance, wrapping this in an option so you could choose whether or not to impart this cost? (presumably somewhat similar to how we wrap the threadsafe check and logic). Does that make sense?

Orthogonally, does this mean shopify is utilizing excon in production? Not that it makes a big difference one way or the other, but it's always interesting (and rewarding) to see where it has been adopted.

@byroot
Copy link
Contributor

byroot commented Feb 2, 2023

Does that remain a concern for something like this?

Right. So at that time my concern was that I'd see Process.pid quite high in stackprof reports. However, since then we discovered that the way stackprof worked at the time had a tendency to inflate native methods a bit (tmm1/stackprof#150). In the end it's really isn't as big as I feared it was.

The fork callback is still worth using IMO, but it's not always convenient. Here you'd need to keep weak references on the connections objects, which would likely be more expensive than a PID check.

Ultimately I think the PID check cost here is totally dwarfed by the time even the smallest HTTP request would take, so I'm not too concerned.

does this mean shopify is utilizing excon in production?

Not directly, it's pulled by one of our other dependencies (https://rubygems.org/gems/avro_turf). We kinda use all the http clients in existence because of various hard dependencies like this one -_-

@geemus
Copy link
Contributor

geemus commented Feb 2, 2023

ah, too bad. I suspect something like "not directly" is a pretty common reason folks are using it. Similarly, having LOTS of different http clients getting looped in sounds all too familiar.

Copy link
Contributor

@geemus geemus left a comment

Choose a reason for hiding this comment

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

LGTM. It sounds like this should help with forks and that the PID check is fairly inexpensive. Still, we'll want to keep an eye on it and can tweak or guard it if it ends up being an issue.

@geemus geemus merged commit 462b62e into excon:master Feb 2, 2023
@byroot
Copy link
Contributor

byroot commented Feb 2, 2023

thanks for the merge!

@geemus
Copy link
Contributor

geemus commented Feb 2, 2023

Also, sorry for referencing the wrong person/account instead of the one this started with, just realized when I saw multiple avatars.

@geemus
Copy link
Contributor

geemus commented Feb 2, 2023

Of course, thanks for the fix. Do you need a release with the change?

@byroot
Copy link
Contributor

byroot commented Feb 2, 2023

wrong person/account

No worries, makes little difference to me.

Do you need a release with the change?

If it's not too much bother for you that's be great. But if you have other changes planned, it can wait.

@geemus
Copy link
Contributor

geemus commented Feb 2, 2023

Sounds good. I'm about to wrap up for the day and want to look at one other bug a little more. One way or the other I'll try to get a release either early tomorrow or early next week.

@geemus
Copy link
Contributor

geemus commented Feb 3, 2023

Released in v0.99.0.

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

3 participants