-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Improvements to out_of_band hook #2234
Conversation
This moves the hook to be executed outside of busy loop considering the thread to be truly idle at a time of execution of the hook
3aa150f
to
58014f4
Compare
lib/puma/server.rb
Outdated
end | ||
end | ||
private :accept_socket | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extracted this logic into a private method both to simplify the accept-loop, but more importantly to allow the to be stubbed in the test_blocks_new_connection
unit-test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, the original ECONNABORTED
rescue clause had io.close
not sock.close
, I should change this back to the original behavior.
That said, the line is ancient, dating back to 2006 (ab3c808) (!) and never covered by any tests, so it's very likely this is 'superstitious' code that should probably be changed/removed separately anyway.
In my reading of the current code, ECONNABORTED
would only ever be thrown by accept_nonblock
(accept
syscall) if the listener socket is closed accepts a connection that was closed while waiting on the listen queue, but in that case io
would be nil
causing io.close
to always fail..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I managed to figure out how to stub the accept
call without needing to extract the method, so I'll move this refactoring/cleanup to a separate PR.
lib/puma/server.rb
Outdated
io.close | ||
rescue | ||
Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue | ||
pool.wait_until_not_full |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moving the call to wait_until_not_full
before accept_socket
prevents connections from being accepted until out_of_band hooks are completed.
(I'm not 100% sure this change won't have any other side-effects, but the test suite seems to think it's okay...)
An alternative would be to just add an extra pool.with_mutex {}
line above accept_socket
.
@@ -224,8 +224,11 @@ def run(background=true) | |||
@reactor.add client | |||
end | |||
end | |||
|
|||
process_now |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This return value of the ThreadPool
block (process_now
is true when a complete request was processed by the block) is used to determine if an OOB hook should be scheduled to fire once the thread is eventually idle.
58014f4
to
bad2be5
Compare
* Don't trigger OOB on partially-queued requests * Don't accept new connections during OOB * Move tests to `TestOutOfBandServer`
bad2be5
to
d416d0c
Compare
end | ||
app_wait = options.delete(:app_wait) | ||
app = ->(_) do | ||
raise 'OOB conflict' if in_oob.locked? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, I like that approach.
Tests are 😍 |
Description
Followup to #2230 (extending the idea to move the OOB hook from
Server
intoThreadPool
), addressing the two extra edge cases described at #2230 (comment).Also:
TestPumaServer
class into its ownTestOutOfBandServer
class(Turns out there are a ton of complicated little edge-cases to consider around what seemed like such a simple feature!)
Your checklist for this pull request
[changelog skip]
the pull request title.[ci skip]
to the title of the PR.#issue
" to the PR description or my commit messages.