diff --git a/docs/raspberry_pi_os_build_instructions.md b/docs/raspberry_pi_os_build_instructions.md index 0e2a1475..2652aa32 100644 --- a/docs/raspberry_pi_os_build_instructions.md +++ b/docs/raspberry_pi_os_build_instructions.md @@ -214,19 +214,19 @@ WorkingDirectory=/home/pi/seedsigner/src/ ExecStart=/usr/bin/python3 main.py StandardOutput=null ErrorOutput=null -Restart=always +Restart=no [Install] WantedBy=multi-user.target ``` -_Note: For local dev you'll want to edit the `Restart=always` line to `Restart=no`. This way when your dev code crashes it won't keep trying to restart itself. Note that the UI "Reset" will no longer work when auto-restarts are disabled._ +_Note: The line `Restart=no` ensures that when your dev code crashes it won't keep trying to restart itself._ _Note: Debugging output is completely wiped via routing the stdout and stderr to `/dev/null`. When working in local dev, you'll `kill` the `systemd` SeedSigner service and just directly run the code on demand so you can see all the debugging output live._ Use `CTRL-X` and `y` to exit and save changes. -Configure the service to start running (this will restart the seedsigner code automatically at startup and if it crashes): +Configure the service to start running (this will restart the seedsigner code automatically at startup): ```bash sudo systemctl enable seedsigner.service ``` diff --git a/src/seedsigner/views/view.py b/src/seedsigner/views/view.py index 66c3a229..462196d3 100644 --- a/src/seedsigner/views/view.py +++ b/src/seedsigner/views/view.py @@ -1,3 +1,4 @@ +import logging from dataclasses import dataclass from gettext import gettext as _ from typing import Type @@ -10,6 +11,9 @@ from seedsigner.models.settings import Settings, SettingsConstants from seedsigner.models.settings_definition import SettingsDefinition from seedsigner.models.threads import BaseThread +logger = logging.getLogger(__name__) + + class BackStackView: """ @@ -242,30 +246,43 @@ class PowerOptionsView(View): return Destination(PowerOffView) - +@dataclass class RestartView(View): + is_screenshot_renderer: bool = False + + def __post_init__(self): + super().__post_init__() + self.thread = self.DoResetThread() + def run(self): + if self.is_screenshot_renderer: + # For the screenshot generator, we don't actually want to restart + return + + logger.info("Restarting SeedSigner") + from seedsigner.gui.screens.screen import ResetScreen - thread = RestartView.DoResetThread() - thread.start() + + self.thread.start() self.run_screen(ResetScreen) class DoResetThread(BaseThread): def run(self): + import os + import sys import time - from subprocess import call # Give the screen just enough time to display the reset message before # exiting. time.sleep(0.25) - # Kill the SeedSigner process; Running the process again. - # `.*` is a wildcard to detect either `python`` or `python3`. - if Settings.HOSTNAME == Settings.SEEDSIGNER_OS: - call("kill $(pidof python*) & python /opt/src/main.py", shell=True) - else: - call("kill $(ps aux | grep '[p]ython.*main.py' | awk '{print $2}')", shell=True) + # Flush any buffered data. + sys.stdout.flush() + sys.stderr.flush() + + # Replace the current process with a new one. + os.execv(sys.executable, [sys.executable] + sys.argv) diff --git a/tests/screenshot_generator/generator.py b/tests/screenshot_generator/generator.py index fce87164..0cc8bfaa 100644 --- a/tests/screenshot_generator/generator.py +++ b/tests/screenshot_generator/generator.py @@ -275,7 +275,7 @@ def generate_screenshots(locale): ScreenshotConfig(MainMenuView, screenshot_name='MainMenuView_DireWarningToast', toast_thread=DireWarningToast("This is a dire warning toast!", activation_delay=0, duration=0)), ScreenshotConfig(MainMenuView, screenshot_name='MainMenuView_ErrorToast', toast_thread=ErrorToast("This is an error toast!", activation_delay=0, duration=0)), ScreenshotConfig(PowerOptionsView), - ScreenshotConfig(RestartView), + ScreenshotConfig(RestartView, dict(is_screenshot_renderer=True)), ScreenshotConfig(PowerOffView), ], "Seed Views": [