Support frozen background pipe tunnel polling on Linux
@@ -381,7 +381,9 @@ def create_background_tunnel(local_port, remote_port, remote_host, log_file, log
def wait_for_background_tunnel(tunnel_proc, local_port, timeout, polling_delay=1):
attempts = int(timeout / polling_delay)
- is_tunnel_ready = is_tunnel_ready_on_mac if is_mac() else is_tunnel_ready_on_lin_and_win
+ is_tunnel_ready = is_tunnel_ready_on_lin
+ is_tunnel_ready = is_tunnel_ready_on_mac if is_mac() else is_tunnel_ready
+ is_tunnel_ready = is_tunnel_ready_on_win if is_windows() else is_tunnel_ready
while attempts > 0:
time.sleep(polling_delay)
if tunnel_proc.poll() is not None:
@@ -399,18 +401,6 @@ def wait_for_background_tunnel(tunnel_proc, local_port, timeout, polling_delay=1
.format(timeout))
-def is_tunnel_ready_on_lin_and_win(tunnel_pid, local_port):
- import psutil
- for net_connection in psutil.net_connections():
- if net_connection.laddr \
- and net_connection.laddr.port == local_port \
- and net_connection.pid == tunnel_pid:
- return True
- return False
-
-def clean_tunnel_pid(pid):
- return pid.strip() if pid and pid.strip().isdigit() else ''
-
def is_tunnel_ready_on_mac(tunnel_pid, local_port):
# psutil.net_connections() is not allowed to a regular user on mac
listening_pid = clean_tunnel_pid(perform_command(['lsof', '-t', '-i', 'TCP:' + str(local_port), '-s', 'TCP:LISTEN'],
@@ -426,6 +416,37 @@ def is_tunnel_ready_on_mac(tunnel_pid, local_port):
(int(listening_pid) == tunnel_pid or int(listening_parent_pid) == tunnel_pid)
+def clean_tunnel_pid(pid):
+ return pid.strip() if pid and pid.strip().isdigit() else ''
+
+
+def is_tunnel_ready_on_lin(tunnel_pid, local_port):
+ listening_pid = get_listening_pid_on_lin_and_win(local_port)
+ listening_parent_pid = get_parent_pid_on_lin_and_win(listening_pid)
+ logging.debug('Waiting for tunnel PID {}, got PID {} listening on port {} with parent PID {}'
+ .format(tunnel_pid, listening_pid, local_port, listening_parent_pid))
+ return listening_pid and \
+ listening_parent_pid and \
+ (listening_pid == tunnel_pid or listening_parent_pid == tunnel_pid)
+
+
+def get_listening_pid_on_lin_and_win(local_port):
+ import psutil
+ for net_connection in psutil.net_connections():
+ if net_connection.laddr and net_connection.laddr.port == local_port:
+ return net_connection.pid
+ return 0
+
+
+def get_parent_pid_on_lin_and_win(pid):
+ import psutil
+ return psutil.Process(pid).ppid() if pid else 0
+
+
+def is_tunnel_ready_on_win(tunnel_pid, local_port):
+ return get_listening_pid_on_lin_and_win(local_port) == tunnel_pid
+
+
def create_foreground_tunnel_with_ssh(run_id, local_port, remote_port, connection_timeout, conn_info,
ssh_path, ssh_keep, remote_host, log_file, log_level, retries):
logging.basicConfig(level=log_level or logging.ERROR, format=DEFAULT_LOGGING_FORMAT)
