From 16815a283ec0373d3deeea8131413e68fbc113c8 Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Mon, 31 Oct 2022 11:01:41 +0100 Subject: [PATCH] own timeout --- cashu/tor/timeout.py | 41 ++++++++++++++++++++++++++++++++ cashu/tor/tor.py | 53 ++++++++++++++++++++++++------------------ cashu/wallet/cli.py | 2 +- cashu/wallet/wallet.py | 6 ++--- tests/test_tor.py | 6 ++--- 5 files changed, 78 insertions(+), 30 deletions(-) create mode 100755 cashu/tor/timeout.py diff --git a/cashu/tor/timeout.py b/cashu/tor/timeout.py new file mode 100755 index 0000000..4306396 --- /dev/null +++ b/cashu/tor/timeout.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python +import os +import signal +import subprocess +import sys +import time + + +def main(): + assert len(sys.argv) > 2, "Usage: timeout.py [seconds] [command...]" + cmd = " ".join(sys.argv[2:]) + timeout = int(sys.argv[1]) + start_time = time.time() + assert timeout > 0, "timeout (in seconds) must be a positive integer." + + pro = subprocess.Popen(cmd, shell=True) + + while time.time() < start_time + timeout: + time.sleep(1) + # check if process is still running + try: + os.getpgid(pro.pid) + except ProcessLookupError: + break + + # terminate process + try: + os.killpg(os.getpgid(pro.pid), signal.SIGTERM) + except ProcessLookupError: + return + + # kill process + time.sleep(1.0) + try: + os.killpg(os.getpgid(pro.pid), signal.SIGKILL) + except ProcessLookupError: + return + + +if __name__ == "__main__": + main() diff --git a/cashu/tor/tor.py b/cashu/tor/tor.py index 995e282..8d53781 100755 --- a/cashu/tor/tor.py +++ b/cashu/tor/tor.py @@ -9,41 +9,46 @@ from loguru import logger class TorProxy: - def __init__(self, keep_alive=False, dont_start=False): + def __init__(self, timeout=False): self.base_path = pathlib.Path(__file__).parent.resolve() self.platform = platform.system() - self.keep_alive = 60 * 60 if keep_alive else 0 # seconds + self.timeout = 60 * 60 if timeout else 0 # seconds self.tor_proc = None self.pid_file = os.path.join(self.base_path, "tor.pid") self.tor_pid = None self.startup_finished = True self.tor_running = self.is_running() - logger.debug(f"Tor running: {self.tor_running}") - logger.debug( - f"Tor port open: {self.is_port_open()}", - ) - logger.debug(f"Tor binary path: {self.tor_path()}") - logger.debug(f"Tor config path: {self.tor_config_path()}") - logger.debug(f"Tor PID in tor.pid: {self.read_pid()}") - logger.debug(f"Tor PID running: {self.signal_pid(self.read_pid())}") - - if not self.tor_running and not dont_start: - self.run_daemon() @classmethod def check_platform(cls): if platform.system() == "Linux": if platform.machine() != "x86_64": + logger.debug("Builtin Tor not supported on this platform.") return False return True - def run_daemon(self): - if not self.check_platform(): + def log_status(self): + logger.debug(f"Tor binary path: {self.tor_path()}") + logger.debug(f"Tor config path: {self.tor_config_path()}") + logger.debug(f"Tor running: {self.tor_running}") + logger.debug( + f"Tor port open: {self.is_port_open()}", + ) + logger.debug(f"Tor PID in tor.pid: {self.read_pid()}") + logger.debug(f"Tor PID running: {self.signal_pid(self.read_pid())}") + + def run_daemon(self, verbose=False): + if not self.check_platform() or self.tor_running: return + self.log_status() logger.debug("Starting Tor") cmd = [f"{self.tor_path()}", "--defaults-torrc", f"{self.tor_config_path()}"] - if self.keep_alive and platform.system() != "Windows": - cmd = ["timeout", f"{self.keep_alive}"] + cmd + if self.timeout: + logger.debug(f"Starting tor with timeout {self.timeout}s") + cmd = [ + os.path.join(self.base_path, "timeout.py"), + f"{self.timeout}", + ] + cmd env = dict(os.environ) if platform.system() == "Linux": env["LD_LIBRARY_PATH"] = os.path.dirname(self.tor_path()) @@ -62,6 +67,8 @@ class TorProxy: with open(self.pid_file, "w", encoding="utf-8") as f: f.write(str(self.tor_proc.pid)) + self.wait_until_startup(verbose=verbose) + def stop_daemon(self, pid=None): pid = pid or self.tor_proc.pid if self.tor_proc else None if self.tor_proc and pid: @@ -92,13 +99,13 @@ class TorProxy: def is_running(self): # our tor proxy running from a previous session if self.signal_pid(self.read_pid()): - logger.debug("Tor proxy already running.") + # logger.debug("Tor proxy already running.") return True # another tor proxy is running if self.is_port_open(): - logger.debug( - "Another Tor instance seems to be already running on port 9050." - ) + # logger.debug( + # "Another Tor instance seems to be already running on port 9050." + # ) return True # current attached process running return self.tor_proc and self.tor_proc.poll() is None @@ -165,8 +172,8 @@ class TorProxy: if __name__ == "__main__": - tor = TorProxy() - tor.wait_until_startup(verbose=True) + tor = TorProxy(timeout=True) + tor.run_daemon(verbose=True) # time.sleep(5) # logger.debug("Killing Tor") # tor.stop_daemon() diff --git a/cashu/wallet/cli.py b/cashu/wallet/cli.py index 3ec7cdd..cb0285c 100755 --- a/cashu/wallet/cli.py +++ b/cashu/wallet/cli.py @@ -72,7 +72,7 @@ def cli(ctx, host: str, walletname: str): ctx.obj["WALLET_NAME"] = walletname wallet = Wallet(ctx.obj["HOST"], os.path.join(CASHU_DIR, walletname)) - if TOR and not TorProxy(dont_start=True).check_platform(): + if TOR and not TorProxy().check_platform(): print( "WARNING: Your settings say TOR=true but the built-in Tor bundle is not supported on your system. Your IP will be visible to the mint! Please install Tor manually and set TOR=false and SOCKS_HOST=localhost and SOCKS_PORT=9050 in your Cashu config (recommended) or turn off Tor altogether by setting TOR=false (not recommended)." ) diff --git a/cashu/wallet/wallet.py b/cashu/wallet/wallet.py index 48bcf3c..5660dff 100644 --- a/cashu/wallet/wallet.py +++ b/cashu/wallet/wallet.py @@ -64,9 +64,9 @@ class LedgerAPI: s = requests.Session() s.headers.update({"Client-version": VERSION}) socks_host, socks_port = None, None - if TOR and TorProxy(dont_start=True).check_platform(): - self.tor = TorProxy(keep_alive=True) - self.tor.wait_until_startup(verbose=True) + if TOR and TorProxy().check_platform(): + self.tor = TorProxy(timeout=True) + self.tor.run_daemon(verbose=True) socks_host, socks_port = "localhost", 9050 else: socks_host, socks_port = SOCKS_HOST, SOCKS_PORT diff --git a/tests/test_tor.py b/tests/test_tor.py index d5f1902..4d792bb 100644 --- a/tests/test_tor.py +++ b/tests/test_tor.py @@ -4,12 +4,12 @@ import requests from cashu.tor.tor import TorProxy -@pytest.mark.skip +# @pytest.mark.skip def test_tor_setup(): s = requests.Session() - tor = TorProxy(keep_alive=False) - tor.wait_until_startup() + tor = TorProxy(timeout=False) + tor.run_daemon() socks_host, socks_port = "localhost", 9050 proxies = {