From: Eric Wong Date: Thu, 24 Jan 2013 19:47:41 +0000 (+0000) Subject: epoll: ensure closing of pipelined clients if required X-Git-Tag: v4.5.0~16 X-Git-Url: https://repo.or.cz/w/rainbows.git/commitdiff_plain/49f70632e2f4a9b84fd4fced7439d0844fed1bbd epoll: ensure closing of pipelined clients if required on_read normally relies on the close checking in on_readable, but on_deferred_write_complete may be called from on_writable instead (bypassing the close check of on_readable). This affects both Epoll and XEpoll users, but only if they were sending responses via body#to_path and triggering on_deferred_write_complete. While we're at it, favor non-recursive want_more instead of calling on_readable recursively in ev_write_responses to prevent stack growth. --- diff --git a/lib/rainbows/epoll/client.rb b/lib/rainbows/epoll/client.rb index f690d85..d72696b 100644 --- a/lib/rainbows/epoll/client.rb +++ b/lib/rainbows/epoll/client.rb @@ -102,7 +102,19 @@ module Rainbows::Epoll::Client else write_response(status, headers, body, alive) end - on_read(Z) if alive && 0 == @wr_queue.size && 0 != @buf.size + # try to read more if we didn't have to buffer writes + next_request if alive && 0 == @wr_queue.size + end + + def next_request + if 0 == @buf.size + want_more + else + # pipelined request (already in buffer) + on_read(Z) + return if @wr_queue[0] || closed? + close if :close == @state + end end def epoll_run @@ -120,7 +132,7 @@ module Rainbows::Epoll::Client def on_deferred_write_complete :close == @state and return close - 0 == @buf.size ? on_readable : on_read(Z) + next_request end def handle_error(e)