Fix #494 sshuttle caught in infinite select() loop.

Improve detection of when the ssh process exits in both daemon and
foreground modes. Previously, sshuttle could infinite loop with 100%
cpu usage if the ssh process died. On machines that use suspend, the
ssh connection might not resume after wakeup. Now, this situation is
detected and sshuttle exits. The fix involves changing the return
value we check for when we call poll() and using a psutil function to
detect when the process exits if we are running sshuttle as a daemon.
This commit is contained in:
Scott Kuhl 2020-09-07 15:39:36 -04:00
parent 19f653df36
commit 5d6b14673f
2 changed files with 17 additions and 4 deletions

View File

@ -1 +1,2 @@
setuptools-scm==4.1.2
psutil

View File

@ -6,6 +6,7 @@ import subprocess as ssubprocess
import os
import sys
import platform
import psutil
import sshuttle.helpers as helpers
import sshuttle.ssnet as ssnet
@ -541,11 +542,22 @@ def _main(tcp_listener, udp_listener, fw, ssh_cmd, remotename,
debug1('seed_hosts: %r\n' % seed_hosts)
mux.send(0, ssnet.CMD_HOST_REQ, str.encode('\n'.join(seed_hosts)))
while 1:
rv = serverproc.poll()
if rv:
raise Fatal('server died with error code %d' % rv)
def check_ssh_alive():
if daemon:
# poll() won't tell us when process exited since the
# process is no longer our child (it returns 0 all the
# time).
if not psutil.pid_exists(serverproc.pid):
raise Fatal('ssh connection to server (pid %d) exited.' % serverproc.pid)
else:
rv = serverproc.poll()
# poll returns None if process hasn't exited.
if rv is not None:
raise Fatal('ssh connection to server (pid %d) exited with returncode %d' % (serverproc.pid, rv))
while 1:
check_ssh_alive()
ssnet.runonce(handlers, mux)
if latency_control:
mux.check_fullness()