From c9af4f794060e218193935d7213f0991a374f502 Mon Sep 17 00:00:00 2001 From: Florian Bruggisser Date: Thu, 28 Sep 2023 22:47:14 +0200 Subject: [PATCH] Added timeout and error handling for frpc tunnel (#5731) * added timeout and error handling for frpc tunnel * add changeset * lint * typing * spell * tunneling * lint * strip --------- Co-authored-by: gradio-pr-bot Co-authored-by: Abubakar Abid --- .changeset/honest-phones-like.md | 5 +++++ gradio/tunneling.py | 37 +++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 .changeset/honest-phones-like.md diff --git a/.changeset/honest-phones-like.md b/.changeset/honest-phones-like.md new file mode 100644 index 000000000000..b0319f71111c --- /dev/null +++ b/.changeset/honest-phones-like.md @@ -0,0 +1,5 @@ +--- +"gradio": patch +--- + +fix:Added timeout and error handling for frpc tunnel diff --git a/gradio/tunneling.py b/gradio/tunneling.py index 7249ff57c7a0..badbdfe1822b 100644 --- a/gradio/tunneling.py +++ b/gradio/tunneling.py @@ -4,6 +4,8 @@ import re import stat import subprocess +import sys +import time from pathlib import Path from typing import List @@ -24,6 +26,12 @@ BINARY_FOLDER = Path(__file__).parent BINARY_PATH = f"{BINARY_FOLDER / BINARY_FILENAME}" +TUNNEL_TIMEOUT_SECONDS = 30 +TUNNEL_ERROR_MESSAGE = ( + "Could not create share URL. " + "Please check the appended log from frpc for more information:" +) + class Tunnel: def __init__(self, remote_host, remote_port, local_host, local_port, share_token): @@ -88,16 +96,43 @@ def _start_tunnel(self, binary: str) -> str: command, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) atexit.register(self.kill) + return self._read_url_from_tunnel_stream() + + def _read_url_from_tunnel_stream(self) -> str: + start_timestamp = time.time() + + log = [] url = "" + + def _raise_tunnel_error(): + log_text = "\n".join(log) + print(log_text, file=sys.stderr) + raise ValueError(f"{TUNNEL_ERROR_MESSAGE}\n{log_text}") + while url == "": + # check for timeout and log + if time.time() - start_timestamp >= TUNNEL_TIMEOUT_SECONDS: + _raise_tunnel_error() + + assert self.proc is not None if self.proc.stdout is None: continue + line = self.proc.stdout.readline() line = line.decode("utf-8") + + if line == "": + continue + + log.append(line.strip()) + if "start proxy success" in line: result = re.search("start proxy success: (.+)\n", line) if result is None: - raise ValueError("Could not create share URL") + _raise_tunnel_error() else: url = result.group(1) + elif "login to server failed" in line: + _raise_tunnel_error() + return url