Merge pull request #1061 from silveraignacio/fix-broken-pipe-handling

fix: improve broken pipe (EPIPE) error handling in socket operations
This commit is contained in:
Brian May
2025-08-02 09:07:33 +10:00
committed by GitHub
2 changed files with 15 additions and 8 deletions

View File

@ -616,7 +616,7 @@ def _main(tcp_listener, udp_listener, fw, ssh_cmd, remotename,
except socket.error as e:
if e.args[0] == errno.EPIPE:
debug3('Error: EPIPE: ' + repr(e))
raise Fatal("failed to establish ssh session (1)")
raise Fatal("SSH connection lost: broken pipe (server may have terminated unexpectedly)")
else:
raise
mux = Mux(rfile, wfile)

View File

@ -80,11 +80,13 @@ def _nb_clean(func, *args):
except (OSError, socket.error):
# Note: In python2 socket.error != OSError (In python3, they are same)
_, e = sys.exc_info()[:2]
if e.errno not in (errno.EWOULDBLOCK, errno.EAGAIN):
raise
else:
if e.errno in (errno.EWOULDBLOCK, errno.EAGAIN):
debug3('%s: err was: %s' % (func.__name__, e))
return None
else:
# Re-raise other errors (including EPIPE) so they can be handled
# by the calling function appropriately
raise
def _try_peername(sock):
@ -220,7 +222,7 @@ class SockWrapper:
self.wsock.setblocking(False)
try:
return _nb_clean(self.wsock.send, buf)
except OSError:
except (OSError, socket.error):
_, e = sys.exc_info()[:2]
if e.errno == errno.EPIPE:
debug1('%r: uwrite: got EPIPE' % self)
@ -243,8 +245,13 @@ class SockWrapper:
self.rsock.setblocking(False)
try:
return _nb_clean(self.rsock.recv, 65536)
except OSError:
except (OSError, socket.error):
_, e = sys.exc_info()[:2]
if e.errno == errno.EPIPE:
debug1('%r: uread: got EPIPE' % self)
self.noread()
return b('') # treat broken pipe as EOF
else:
self.seterr('uread: %s' % e)
return b('') # unexpected error... we'll call it EOF