@@ -2747,7 +2747,7 @@ mod _ssl {
27472747
27482748 /// Flush any pending TLS output data to the socket
27492749 /// This should be called before generating new TLS output
2750- fn flush_pending_tls_output ( & self , vm : & VirtualMachine ) -> PyResult < ( ) > {
2750+ pub ( crate ) fn flush_pending_tls_output ( & self , vm : & VirtualMachine ) -> PyResult < ( ) > {
27512751 let mut pending = self . pending_tls_output . lock ( ) ;
27522752 if pending. is_empty ( ) {
27532753 return Ok ( ( ) ) ;
@@ -3919,7 +3919,8 @@ mod _ssl {
39193919 if current_state == ShutdownState :: NotStarted {
39203920 // First, flush any pending TLS data BEFORE sending close_notify
39213921 // This ensures all application data is sent before the shutdown alert
3922- self . flush_pending_tls_output ( vm) ?;
3922+ // Ignore errors - pending data will be sent with close_notify
3923+ let _ = self . flush_pending_tls_output ( vm) ;
39233924
39243925 conn. send_close_notify ( ) ;
39253926
@@ -3973,7 +3974,7 @@ mod _ssl {
39733974 if self . try_read_close_notify ( conn, vm) ? {
39743975 peer_closed = true ;
39753976 }
3976- } else if let Some ( _timeout ) = timeout_mode {
3977+ } else if let Some ( timeout ) = timeout_mode {
39773978 // All socket modes (blocking, timeout, non-blocking):
39783979 // Return immediately after sending our close_notify.
39793980 //
@@ -3989,7 +3990,24 @@ mod _ssl {
39893990 // This prevents data loss when rustls drains its buffer
39903991 // but the socket couldn't accept all data immediately
39913992 drop ( conn_guard) ;
3992- self . blocking_flush_all_pending ( vm) ?;
3993+
3994+ // Respect socket timeout settings for flushing pending TLS data
3995+ match timeout {
3996+ Some ( 0.0 ) => {
3997+ // Non-blocking: best-effort flush, ignore errors
3998+ // to avoid deadlock with asyncore-based servers
3999+ let _ = self . flush_pending_tls_output ( vm) ;
4000+ }
4001+ Some ( _t) => {
4002+ // Timeout mode: use flush with socket's timeout
4003+ // Errors (including timeout) are propagated to caller
4004+ self . flush_pending_tls_output ( vm) ?;
4005+ }
4006+ None => {
4007+ // Blocking mode: wait until all pending data is sent
4008+ self . blocking_flush_all_pending ( vm) ?;
4009+ }
4010+ }
39934011
39944012 * self . shutdown_state . lock ( ) = ShutdownState :: Completed ;
39954013 * self . connection . lock ( ) = None ;
@@ -4022,7 +4040,8 @@ mod _ssl {
40224040 // Helper: Write all pending TLS data (including close_notify) to outgoing buffer/BIO
40234041 fn write_pending_tls ( & self , conn : & mut TlsConnection , vm : & VirtualMachine ) -> PyResult < ( ) > {
40244042 // First, flush any previously pending TLS output
4025- self . flush_pending_tls_output ( vm) ?;
4043+ // Ignore errors - they will be retried with the new data
4044+ let _ = self . flush_pending_tls_output ( vm) ;
40264045
40274046 loop {
40284047 if !conn. wants_write ( ) {
0 commit comments