diff --git a/SickBeard.py b/SickBeard.py index 8da08582..73da7602 100755 --- a/SickBeard.py +++ b/SickBeard.py @@ -54,10 +54,10 @@ import getopt import sickbeard -from sickbeard.webserveInit import webserverInit from sickbeard import db from sickbeard.tv import TVShow from sickbeard import logger +from sickbeard import webserveInit from sickbeard.version import SICKBEARD_VERSION from sickbeard.databases.mainDB import MIN_DB_VERSION from sickbeard.databases.mainDB import MAX_DB_VERSION @@ -146,13 +146,6 @@ def daemonize(): os.dup2(stdout.fileno(), sys.stdout.fileno()) os.dup2(stderr.fileno(), sys.stderr.fileno()) - -# background update every x seconds -def invoke_command(): - if sickbeard.invoked_command: - sickbeard.invoked_command() - sickbeard.invoked_command = None - def main(): """ TV for me @@ -368,11 +361,14 @@ def main(): 'https_key': sickbeard.HTTPS_KEY, } - def startup(): - # Build from the DB to start with - logger.log(u"Loading initial show list") - loadShowsFromDB() + # init tornado + webserveInit.initWebServer(options) + # Build from the DB to start with + logger.log(u"Loading initial show list") + loadShowsFromDB() + + def startup(): # Fire up all our threads sickbeard.start() @@ -384,17 +380,11 @@ def main(): if forceUpdate or sickbeard.UPDATE_SHOWS_ON_START: sickbeard.showUpdateScheduler.action.run(force=True) # @UndefinedVariable - # init tornado - sickbeard.WEBSERVER = webserverInit(options) - sickbeard.WEBSERVER.ioloop.add_timeout(datetime.timedelta(seconds=5), startup) + # init startup tasks + IOLoop.current().add_timeout(datetime.timedelta(seconds=5), startup) - # check for commands to be executed in the background - task = PeriodicCallback(invoke_command, 1000) - sickbeard.WEBSERVER.tasks.append(task) - - # start tornado - sickbeard.WEBSERVER.start() - sickbeard.WEBSERVER.close() + # start IOLoop + IOLoop.current().start() return if __name__ == "__main__": diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py index 8ebf4c8e..1280dd81 100644 --- a/sickbeard/__init__.py +++ b/sickbeard/__init__.py @@ -53,8 +53,6 @@ from lib.configobj import ConfigObj from tornado.ioloop import IOLoop import xml.etree.ElementTree as ElementTree -invoked_command = None - PID = None CFG = None @@ -77,7 +75,6 @@ PIDFILE = '' DAEMON = None NO_RESIZE = False -WEBSERVER = None maintenanceScheduler = None dailySearchScheduler = None @@ -1117,15 +1114,12 @@ def start(): showUpdateScheduler, versionCheckScheduler, showQueueScheduler, \ properFinderScheduler, autoPostProcesserScheduler, searchQueueScheduler, \ subtitlesFinderScheduler, USE_SUBTITLES,traktWatchListCheckerScheduler, \ - dailySearchScheduler, WEBSERVER, started + dailySearchScheduler, started with INIT_LOCK: if __INITIALIZED__: - # start IOLoop tasks - WEBSERVER.start_tasks() - # start the maintenance scheduler maintenanceScheduler.thread.start() logger.log(u"Performing initial maintenance tasks, please wait ...") @@ -1171,7 +1165,7 @@ def halt(): showUpdateScheduler, versionCheckScheduler, showQueueScheduler, \ properFinderScheduler, autoPostProcesserScheduler, searchQueueScheduler, \ subtitlesFinderScheduler, traktWatchListCheckerScheduler, \ - dailySearchScheduler, WEBSERVER, started + dailySearchScheduler, started with INIT_LOCK: @@ -1181,8 +1175,6 @@ def halt(): # abort all the threads - WEBSERVER.stop_tasks() - maintenanceScheduler.abort = True logger.log(u"Waiting for the MAINTENANCE scheduler thread to exit") try: @@ -1190,6 +1182,13 @@ def halt(): except: pass + dailySearchScheduler.abort = True + logger.log(u"Waiting for the DAILYSEARCH thread to exit") + try: + dailySearchScheduler.thread.join(10) + except: + pass + backlogSearchScheduler.abort = True logger.log(u"Waiting for the BACKLOG thread to exit") try: @@ -1281,7 +1280,6 @@ def sig_handler(signum=None, frame=None): logger.log(u"Signal %i caught, saving and exiting..." % int(signum)) saveAndShutdown() - def saveAll(): global showList @@ -1294,21 +1292,19 @@ def saveAll(): logger.log(u"Saving config file to disk") save_config() - def saveAndShutdown(restart=False): - global WEBSERVER - - halt() - saveAll() logger.log('Shutting down tornado') try: - WEBSERVER.stop() + IOLoop.current().stop() except RuntimeError: pass except: logger.log('Failed shutting down the server: %s' % traceback.format_exc(), logger.ERROR) + halt() + saveAll() + if CREATEPID: logger.log(u"Removing pidfile " + str(PIDFILE)) remove_pid_file(PIDFILE) @@ -1341,17 +1337,15 @@ def saveAndShutdown(restart=False): os._exit(0) - def invoke_command(to_call, *args, **kwargs): - global invoked_command def delegate(): to_call(*args, **kwargs) - invoked_command = delegate - logger.log(u"Placed invoked command: " + repr(invoked_command) + " for " + repr(to_call) + " with " + repr( + logger.log(u"Placed invoked command: " + repr(delegate) + " for " + repr(to_call) + " with " + repr( args) + " and " + repr(kwargs), logger.DEBUG) + IOLoop.current().add_callback(delegate) def invoke_restart(soft=True): invoke_command(restart, soft=soft) diff --git a/sickbeard/webserveInit.py b/sickbeard/webserveInit.py index d2d0f0ff..577ce516 100644 --- a/sickbeard/webserveInit.py +++ b/sickbeard/webserveInit.py @@ -1,5 +1,4 @@ import os -import datetime import sickbeard import webserve @@ -7,7 +6,6 @@ from sickbeard import logger from sickbeard.helpers import create_https_certificates from tornado.web import Application, StaticFileHandler, RedirectHandler, HTTPError from tornado.httpserver import HTTPServer -from tornado.ioloop import IOLoop class MultiStaticFileHandler(StaticFileHandler): def initialize(self, paths, default_filename=None): @@ -29,139 +27,108 @@ class MultiStaticFileHandler(StaticFileHandler): # Oops file not found anywhere! raise HTTPError(404) +def initWebServer(options={}): + options.setdefault('port', 8081) + options.setdefault('host', '0.0.0.0') + options.setdefault('log_dir', None) + options.setdefault('username', '') + options.setdefault('password', '') + options.setdefault('web_root', '/') + assert isinstance(options['port'], int) + assert 'data_root' in options -class webserverInit(): - def __init__(self, options, cycleTime=datetime.timedelta(seconds=3)): + def http_error_401_hander(status, message, traceback, version): + """ Custom handler for 401 error """ + if status != "401 Unauthorized": + logger.log(u"Tornado caught an error: %s %s" % (status, message), logger.ERROR) + logger.log(traceback, logger.DEBUG) + return r''' + +
+