Skip to content

Commit 0ea4e3d

Browse files
fix(proxy): handle ssl.SSLWantWriteError for large SSL responses
ssl.SSLSocket.send() raises ssl.SSLWantWriteError (not BlockingIOError) when the underlying TCP buffer is full on a non-blocking SSL socket. SSLWantWriteError is a subclass of OSError, so it was caught by the generic connection-close handler, closing the connection mid-response. The client socket stayed open, leaving the caller hanging indefinitely. Catch SSLWantWriteError alongside BlockingIOError in both send paths so SSL connections correctly register EVENT_WRITE and retry when buffer space becomes available. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent c8c7f14 commit 0ea4e3d

1 file changed

Lines changed: 2 additions & 2 deletions

File tree

postgresql_proxy/proxy.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ def service_connection(self, key: SelectorKeyProxy, mask):
267267
# All data drained; stop watching for writability.
268268
conn.events = selectors.EVENT_READ
269269
self.selector.modify(sock, selectors.EVENT_READ, data=conn)
270-
except BlockingIOError:
270+
except (BlockingIOError, ssl.SSLWantWriteError):
271271
pass # Still full; will retry on the next EVENT_WRITE notification.
272272
except OSError as e:
273273
LOG.debug('%s closed while flushing backlog: %s', conn.name, e)
@@ -286,7 +286,7 @@ def service_connection(self, key: SelectorKeyProxy, mask):
286286
if next_conn.events & selectors.EVENT_WRITE:
287287
next_conn.events = selectors.EVENT_READ
288288
self.selector.modify(next_conn.sock, selectors.EVENT_READ, data=next_conn)
289-
except BlockingIOError:
289+
except (BlockingIOError, ssl.SSLWantWriteError):
290290
# next_conn's send buffer is full — register for writability so we retry when there's space.
291291
if not (next_conn.events & selectors.EVENT_WRITE):
292292
next_conn.events = selectors.EVENT_READ | selectors.EVENT_WRITE

0 commit comments

Comments
 (0)