Fixes for issue #1114

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.
This commit is contained in:
Ryan Kraus 2016-02-06 09:48:36 -05:00
parent 614034d196
commit 11a2b8888b
3 changed files with 42 additions and 14 deletions

View File

@ -10,7 +10,8 @@ import argparse
from homeassistant import bootstrap from homeassistant import bootstrap
import homeassistant.config as config_util 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(): def validate_python():
@ -76,6 +77,11 @@ def get_arguments():
'--demo-mode', '--demo-mode',
action='store_true', action='store_true',
help='Start Home Assistant in demo mode') 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( parser.add_argument(
'--open-ui', '--open-ui',
action='store_true', action='store_true',
@ -207,8 +213,11 @@ def uninstall_osx():
print("Home Assistant has been uninstalled.") print("Home Assistant has been uninstalled.")
def setup_and_run_hass(config_dir, args): def setup_and_run_hass(config_dir, args, top_process=False):
""" Setup HASS and run. Block until stopped. """ """
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: if args.demo_mode:
config = { config = {
'frontend': {}, 'frontend': {},
@ -235,7 +244,11 @@ def setup_and_run_hass(config_dir, args):
hass.bus.listen_once(EVENT_HOMEASSISTANT_START, open_browser) hass.bus.listen_once(EVENT_HOMEASSISTANT_START, open_browser)
hass.start() 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): def run_hass_process(hass_proc):
@ -262,7 +275,10 @@ def run_hass_process(hass_proc):
hass_proc.join() hass_proc.join()
except KeyboardInterrupt: except KeyboardInterrupt:
return False 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(): def main():
@ -277,14 +293,14 @@ def main():
# os x launchd functions # os x launchd functions
if args.install_osx: if args.install_osx:
install_osx() install_osx()
return return 0
if args.uninstall_osx: if args.uninstall_osx:
uninstall_osx() uninstall_osx()
return return 0
if args.restart_osx: if args.restart_osx:
uninstall_osx() uninstall_osx()
install_osx() install_osx()
return return 0
# daemon functions # daemon functions
if args.pid_file: if args.pid_file:
@ -294,12 +310,23 @@ def main():
if args.pid_file: if args.pid_file:
write_pid(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. # Run hass as child process. Restart if necessary.
keep_running = True keep_running = True
while keep_running: while keep_running:
hass_proc = Process(target=setup_and_run_hass, args=(config_dir, args)) 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__": if __name__ == "__main__":
main() sys.exit(main())

View File

@ -197,3 +197,6 @@ HTTP_HEADER_EXPIRES = "Expires"
CONTENT_TYPE_JSON = "application/json" CONTENT_TYPE_JSON = "application/json"
CONTENT_TYPE_MULTIPART = 'multipart/x-mixed-replace; boundary={}' CONTENT_TYPE_MULTIPART = 'multipart/x-mixed-replace; boundary={}'
CONTENT_TYPE_TEXT_PLAIN = 'text/plain' CONTENT_TYPE_TEXT_PLAIN = 'text/plain'
# The exit code to send to request a restart
RESTART_EXIT_CODE = 100

View File

@ -20,7 +20,8 @@ from homeassistant.const import (
EVENT_TIME_CHANGED, EVENT_STATE_CHANGED, EVENT_TIME_CHANGED, EVENT_STATE_CHANGED,
EVENT_CALL_SERVICE, ATTR_NOW, ATTR_DOMAIN, ATTR_SERVICE, MATCH_ALL, EVENT_CALL_SERVICE, ATTR_NOW, ATTR_DOMAIN, ATTR_SERVICE, MATCH_ALL,
EVENT_SERVICE_EXECUTED, ATTR_SERVICE_CALL_ID, EVENT_SERVICE_REGISTERED, 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 ( from homeassistant.exceptions import (
HomeAssistantError, InvalidEntityFormatError) HomeAssistantError, InvalidEntityFormatError)
import homeassistant.util as util import homeassistant.util as util
@ -48,9 +49,6 @@ _LOGGER = logging.getLogger(__name__)
# Temporary to support deprecated methods # Temporary to support deprecated methods
_MockHA = namedtuple("MockHomeAssistant", ['bus']) _MockHA = namedtuple("MockHomeAssistant", ['bus'])
# The exit code to send to request a restart
RESTART_EXIT_CODE = 100
class HomeAssistant(object): class HomeAssistant(object):
"""Root object of the Home Assistant home automation.""" """Root object of the Home Assistant home automation."""