From 11a2b8888b748b44004a2b0d4bbbbf06e95854d4 Mon Sep 17 00:00:00 2001 From: Ryan Kraus Date: Sat, 6 Feb 2016 09:48:36 -0500 Subject: [PATCH] Fixes for issue #1114 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Moved RESTART_EXIT_CODE to constants so it can safely be used by __main__.py. 2. Allowed __main__/main to return the desired exit code. 3. Forwarded the child processes exit code to the parent process to be duplicated. 4. Added —debug flag to pass command to force Home Assistant to run in only one process. A warning is printed to STDERR to indicate HASS is in debug mode. Another is printed if HASS requests a restart in debug mode. A restart request in debug mode will quit. 5. Added an argument to __main__/main/setup_and_run_hass to indicate that it is running in the top process. This tells it to return the exit code rather than exiting. --- homeassistant/__main__.py | 47 ++++++++++++++++++++++++++++++--------- homeassistant/const.py | 3 +++ homeassistant/core.py | 6 ++--- 3 files changed, 42 insertions(+), 14 deletions(-) diff --git a/homeassistant/__main__.py b/homeassistant/__main__.py index d7cfd0a2f00..64eca13356a 100644 --- a/homeassistant/__main__.py +++ b/homeassistant/__main__.py @@ -10,7 +10,8 @@ import argparse from homeassistant import bootstrap import homeassistant.config as config_util -from homeassistant.const import __version__, EVENT_HOMEASSISTANT_START +from homeassistant.const import (__version__, EVENT_HOMEASSISTANT_START, + RESTART_EXIT_CODE) def validate_python(): @@ -76,6 +77,11 @@ def get_arguments(): '--demo-mode', action='store_true', help='Start Home Assistant in demo mode') + parser.add_argument( + '--debug', + action='store_true', + help='Start Home Assistant in debug mode. Runs in single process to ' + 'enable use of interactive debuggers.') parser.add_argument( '--open-ui', action='store_true', @@ -207,8 +213,11 @@ def uninstall_osx(): print("Home Assistant has been uninstalled.") -def setup_and_run_hass(config_dir, args): - """ Setup HASS and run. Block until stopped. """ +def setup_and_run_hass(config_dir, args, top_process=False): + """ + Setup HASS and run. Block until stopped. Will assume it is running in a + subprocess unless top_process is set to true. + """ if args.demo_mode: config = { 'frontend': {}, @@ -235,7 +244,11 @@ def setup_and_run_hass(config_dir, args): hass.bus.listen_once(EVENT_HOMEASSISTANT_START, open_browser) hass.start() - sys.exit(int(hass.block_till_stopped())) + exit_code = int(hass.block_till_stopped()) + + if not top_process: + sys.exit(exit_code) + return exit_code def run_hass_process(hass_proc): @@ -262,7 +275,10 @@ def run_hass_process(hass_proc): hass_proc.join() except KeyboardInterrupt: return False - return not requested_stop.isSet() and hass_proc.exitcode == 100 + + return (not requested_stop.isSet() and + hass_proc.exitcode == RESTART_EXIT_CODE, + hass_proc.exitcode) def main(): @@ -277,14 +293,14 @@ def main(): # os x launchd functions if args.install_osx: install_osx() - return + return 0 if args.uninstall_osx: uninstall_osx() - return + return 0 if args.restart_osx: uninstall_osx() install_osx() - return + return 0 # daemon functions if args.pid_file: @@ -294,12 +310,23 @@ def main(): if args.pid_file: write_pid(args.pid_file) + # Run hass in debug mode if requested + if args.debug: + sys.stderr.write('Running in debug mode. ' + 'Home Assistant will not be able to restart.\n') + exit_code = setup_and_run_hass(config_dir, args, top_process=True) + if exit_code == RESTART_EXIT_CODE: + sys.stderr.write('Home Assistant requested a ' + 'restart in debug mode.\n') + return exit_code + # Run hass as child process. Restart if necessary. keep_running = True while keep_running: hass_proc = Process(target=setup_and_run_hass, args=(config_dir, args)) - keep_running = run_hass_process(hass_proc) + keep_running, exit_code = run_hass_process(hass_proc) + return exit_code if __name__ == "__main__": - main() + sys.exit(main()) diff --git a/homeassistant/const.py b/homeassistant/const.py index cd711df44cd..42146895a01 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -197,3 +197,6 @@ HTTP_HEADER_EXPIRES = "Expires" CONTENT_TYPE_JSON = "application/json" CONTENT_TYPE_MULTIPART = 'multipart/x-mixed-replace; boundary={}' CONTENT_TYPE_TEXT_PLAIN = 'text/plain' + +# The exit code to send to request a restart +RESTART_EXIT_CODE = 100 diff --git a/homeassistant/core.py b/homeassistant/core.py index 936a068480f..c4dbd1562a5 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -20,7 +20,8 @@ from homeassistant.const import ( EVENT_TIME_CHANGED, EVENT_STATE_CHANGED, EVENT_CALL_SERVICE, ATTR_NOW, ATTR_DOMAIN, ATTR_SERVICE, MATCH_ALL, EVENT_SERVICE_EXECUTED, ATTR_SERVICE_CALL_ID, EVENT_SERVICE_REGISTERED, - TEMP_CELCIUS, TEMP_FAHRENHEIT, ATTR_FRIENDLY_NAME, ATTR_SERVICE_DATA) + TEMP_CELCIUS, TEMP_FAHRENHEIT, ATTR_FRIENDLY_NAME, ATTR_SERVICE_DATA, + RESTART_EXIT_CODE) from homeassistant.exceptions import ( HomeAssistantError, InvalidEntityFormatError) import homeassistant.util as util @@ -48,9 +49,6 @@ _LOGGER = logging.getLogger(__name__) # Temporary to support deprecated methods _MockHA = namedtuple("MockHomeAssistant", ['bus']) -# The exit code to send to request a restart -RESTART_EXIT_CODE = 100 - class HomeAssistant(object): """Root object of the Home Assistant home automation."""