@@ -130,6 +130,9 @@ def accept_wrapper(self, sock: socket.socket):
130130
131131 # Accept the raw connection
132132 clientsocket , address = sock .accept ()
133+ # On macOS, accepted sockets inherit O_NONBLOCK from the listening socket.
134+ # SSL negotiation uses blocking recv, so we must set blocking explicitly here.
135+ clientsocket .setblocking (True )
133136
134137 # Check if SSL is enabled for this proxy
135138 if self .ssl_context :
@@ -234,6 +237,15 @@ def service_connection(self, key: SelectorKeyProxy, mask):
234237 if recv_data :
235238 LOG .debug ('%s received data:\n %s' , conn .name , recv_data )
236239 conn .received (recv_data )
240+ # excerpt from https://docs.python.org/3/library/ssl.html#ssl-nonblocking
241+ # Conversely, since the SSL layer has its own framing, a SSL socket may still have data available
242+ # for reading without select() being aware of it. Therefore, you should first call SSLSocket.recv()
243+ # to drain any potentially available data, and then only block on a select() call if still necessary.
244+ while isinstance (sock , ssl .SSLSocket ) and sock .pending () > 0 :
245+ extra = sock .recv (4096 )
246+ if extra :
247+ LOG .debug ('%s received pending SSL data:\n %s' , conn .name , extra )
248+ conn .received (extra )
237249 else :
238250 self ._unregister_conn (conn )
239251 LOG .debug ('%s connection closing %s' , conn .name , conn .address )
0 commit comments