Skip to content

Commit 5ab40f2

Browse files
abhinavsinghYK-Samgopre-commit-ci[bot]
authored
Wait until buffer flush (#1385)
* Wait until all data in buffer is flushed to client when upstream server finishes. (cherry picked from commit d776506) * Wait until buffer flush * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Avoid shadowing * _teared not _teardown * Refactor logic * Do not try `read_from_descriptors` if reads have previously teared down * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: yk <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 2fa320d commit 5ab40f2

File tree

4 files changed

+43
-25
lines changed

4 files changed

+43
-25
lines changed

helper/monitor_open_files.sh

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,20 @@ if [[ -z "$PROXY_PY_PID" ]]; then
2020
exit 1
2121
fi
2222

23-
OPEN_FILES_BY_MAIN=$(lsof -p "$PROXY_PY_PID" | wc -l)
24-
echo "[$PROXY_PY_PID] Main process: $OPEN_FILES_BY_MAIN"
23+
while true;
24+
do
25+
OPEN_FILES_BY_MAIN=$(lsof -p "$PROXY_PY_PID" | wc -l)
26+
echo "[$PROXY_PY_PID] Main process: $OPEN_FILES_BY_MAIN"
2527

26-
pgrep -P "$PROXY_PY_PID" | while read -r acceptorPid; do
27-
OPEN_FILES_BY_ACCEPTOR=$(lsof -p "$acceptorPid" | wc -l)
28-
echo "[$acceptorPid] Acceptor process: $OPEN_FILES_BY_ACCEPTOR"
28+
pgrep -P "$PROXY_PY_PID" | while read -r acceptorPid; do
29+
OPEN_FILES_BY_ACCEPTOR=$(lsof -p "$acceptorPid" | wc -l)
30+
echo "[$acceptorPid] Acceptor process: $OPEN_FILES_BY_ACCEPTOR"
2931

30-
pgrep -P "$acceptorPid" | while read -r childPid; do
31-
OPEN_FILES_BY_CHILD_PROC=$(lsof -p "$childPid" | wc -l)
32-
echo " [$childPid] child process: $OPEN_FILES_BY_CHILD_PROC"
32+
pgrep -P "$acceptorPid" | while read -r childPid; do
33+
OPEN_FILES_BY_CHILD_PROC=$(lsof -p "$childPid" | wc -l)
34+
echo " [$childPid] child process: $OPEN_FILES_BY_CHILD_PROC"
35+
done
3336
done
37+
38+
sleep 1
3439
done

proxy/core/connection/connection.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,11 @@ def flush(self, max_send_size: Optional[int] = None) -> int:
8787
# TODO: Assemble multiple packets if total
8888
# size remains below max send size.
8989
max_send_size = max_send_size or DEFAULT_MAX_SEND_SIZE
90-
sent: int = self.send(mv[:max_send_size])
90+
try:
91+
sent: int = self.send(mv[:max_send_size])
92+
except BlockingIOError:
93+
logger.warning('BlockingIOError when trying send to {0}'.format(self.tag))
94+
return 0
9195
if sent == len(mv):
9296
self.buffer.pop(0)
9397
self._num_buffer -= 1

proxy/http/handler.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ def __init__(self, *args: Any, **kwargs: Any):
4949
if not self.flags.threadless:
5050
self.selector = selectors.DefaultSelector()
5151
self.plugin: Optional[HttpProtocolHandlerPlugin] = None
52+
self.writes_teared: bool = False
53+
self.reads_teared: bool = False
5254

5355
##
5456
# initialize, is_inactive, shutdown, get_events, handle_events
@@ -137,23 +139,26 @@ async def handle_events(
137139
) -> bool:
138140
"""Returns True if proxy must tear down."""
139141
# Flush buffer for ready to write sockets
140-
teardown = await self.handle_writables(writables)
141-
if teardown:
142+
self.writes_teared = await self.handle_writables(writables)
143+
if self.writes_teared:
142144
return True
143145
# Invoke plugin.write_to_descriptors
144146
if self.plugin:
145-
teardown = await self.plugin.write_to_descriptors(writables)
146-
if teardown:
147+
self.writes_teared = await self.plugin.write_to_descriptors(writables)
148+
if self.writes_teared:
147149
return True
148-
# Read from ready to read sockets
149-
teardown = await self.handle_readables(readables)
150-
if teardown:
150+
# Read from ready to read sockets if reads have not already teared down
151+
if not self.reads_teared:
152+
self.reads_teared = await self.handle_readables(readables)
153+
if not self.reads_teared:
154+
# Invoke plugin.read_from_descriptors
155+
if self.plugin:
156+
self.reads_teared = await self.plugin.read_from_descriptors(
157+
readables,
158+
)
159+
# Wait until client buffer has flushed when reads has teared down but we can still write
160+
if self.reads_teared and not self.work.has_buffer():
151161
return True
152-
# Invoke plugin.read_from_descriptors
153-
if self.plugin:
154-
teardown = await self.plugin.read_from_descriptors(readables)
155-
if teardown:
156-
return True
157162
return False
158163

159164
def handle_data(self, data: memoryview) -> Optional[bool]:

proxy/http/proxy/server.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,11 @@ async def get_descriptors(self) -> Descriptors:
175175
return r, w
176176

177177
async def write_to_descriptors(self, w: Writables) -> bool:
178-
if (self.upstream and self.upstream.connection.fileno() not in w) or not self.upstream:
178+
if (
179+
self.upstream
180+
and not self.upstream.closed
181+
and self.upstream.connection.fileno() not in w
182+
) or not self.upstream:
179183
# Currently, we just call write/read block of each plugins. It is
180184
# plugins responsibility to ignore this callback, if passed descriptors
181185
# doesn't contain the descriptor they registered.
@@ -208,9 +212,9 @@ async def write_to_descriptors(self, w: Writables) -> bool:
208212

209213
async def read_from_descriptors(self, r: Readables) -> bool:
210214
if (
211-
self.upstream and not
212-
self.upstream.closed and
213-
self.upstream.connection.fileno() not in r
215+
self.upstream
216+
and not self.upstream.closed
217+
and self.upstream.connection.fileno() not in r
214218
) or not self.upstream:
215219
# Currently, we just call write/read block of each plugins. It is
216220
# plugins responsibility to ignore this callback, if passed descriptors

0 commit comments

Comments
 (0)