1
0
mirror of https://github.com/moparisthebest/SickRage synced 2024-08-13 16:53:54 -04:00

Fixes more issues that were preventing proper shutdowns, restarts, and upgrades.

This commit is contained in:
echel0n 2014-06-15 12:11:21 -07:00
parent fa01711192
commit 7d52d079fa
3 changed files with 117 additions and 166 deletions

View File

@ -54,10 +54,10 @@ import getopt
import sickbeard import sickbeard
from sickbeard.webserveInit import webserverInit
from sickbeard import db from sickbeard import db
from sickbeard.tv import TVShow from sickbeard.tv import TVShow
from sickbeard import logger from sickbeard import logger
from sickbeard import webserveInit
from sickbeard.version import SICKBEARD_VERSION from sickbeard.version import SICKBEARD_VERSION
from sickbeard.databases.mainDB import MIN_DB_VERSION from sickbeard.databases.mainDB import MIN_DB_VERSION
from sickbeard.databases.mainDB import MAX_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(stdout.fileno(), sys.stdout.fileno())
os.dup2(stderr.fileno(), sys.stderr.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(): def main():
""" """
TV for me TV for me
@ -368,11 +361,14 @@ def main():
'https_key': sickbeard.HTTPS_KEY, 'https_key': sickbeard.HTTPS_KEY,
} }
def startup(): # init tornado
# Build from the DB to start with webserveInit.initWebServer(options)
logger.log(u"Loading initial show list")
loadShowsFromDB()
# Build from the DB to start with
logger.log(u"Loading initial show list")
loadShowsFromDB()
def startup():
# Fire up all our threads # Fire up all our threads
sickbeard.start() sickbeard.start()
@ -384,17 +380,11 @@ def main():
if forceUpdate or sickbeard.UPDATE_SHOWS_ON_START: if forceUpdate or sickbeard.UPDATE_SHOWS_ON_START:
sickbeard.showUpdateScheduler.action.run(force=True) # @UndefinedVariable sickbeard.showUpdateScheduler.action.run(force=True) # @UndefinedVariable
# init tornado # init startup tasks
sickbeard.WEBSERVER = webserverInit(options) IOLoop.current().add_timeout(datetime.timedelta(seconds=5), startup)
sickbeard.WEBSERVER.ioloop.add_timeout(datetime.timedelta(seconds=5), startup)
# check for commands to be executed in the background # start IOLoop
task = PeriodicCallback(invoke_command, 1000) IOLoop.current().start()
sickbeard.WEBSERVER.tasks.append(task)
# start tornado
sickbeard.WEBSERVER.start()
sickbeard.WEBSERVER.close()
return return
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -53,8 +53,6 @@ from lib.configobj import ConfigObj
from tornado.ioloop import IOLoop from tornado.ioloop import IOLoop
import xml.etree.ElementTree as ElementTree import xml.etree.ElementTree as ElementTree
invoked_command = None
PID = None PID = None
CFG = None CFG = None
@ -77,7 +75,6 @@ PIDFILE = ''
DAEMON = None DAEMON = None
NO_RESIZE = False NO_RESIZE = False
WEBSERVER = None
maintenanceScheduler = None maintenanceScheduler = None
dailySearchScheduler = None dailySearchScheduler = None
@ -1117,15 +1114,12 @@ def start():
showUpdateScheduler, versionCheckScheduler, showQueueScheduler, \ showUpdateScheduler, versionCheckScheduler, showQueueScheduler, \
properFinderScheduler, autoPostProcesserScheduler, searchQueueScheduler, \ properFinderScheduler, autoPostProcesserScheduler, searchQueueScheduler, \
subtitlesFinderScheduler, USE_SUBTITLES,traktWatchListCheckerScheduler, \ subtitlesFinderScheduler, USE_SUBTITLES,traktWatchListCheckerScheduler, \
dailySearchScheduler, WEBSERVER, started dailySearchScheduler, started
with INIT_LOCK: with INIT_LOCK:
if __INITIALIZED__: if __INITIALIZED__:
# start IOLoop tasks
WEBSERVER.start_tasks()
# start the maintenance scheduler # start the maintenance scheduler
maintenanceScheduler.thread.start() maintenanceScheduler.thread.start()
logger.log(u"Performing initial maintenance tasks, please wait ...") logger.log(u"Performing initial maintenance tasks, please wait ...")
@ -1171,7 +1165,7 @@ def halt():
showUpdateScheduler, versionCheckScheduler, showQueueScheduler, \ showUpdateScheduler, versionCheckScheduler, showQueueScheduler, \
properFinderScheduler, autoPostProcesserScheduler, searchQueueScheduler, \ properFinderScheduler, autoPostProcesserScheduler, searchQueueScheduler, \
subtitlesFinderScheduler, traktWatchListCheckerScheduler, \ subtitlesFinderScheduler, traktWatchListCheckerScheduler, \
dailySearchScheduler, WEBSERVER, started dailySearchScheduler, started
with INIT_LOCK: with INIT_LOCK:
@ -1181,8 +1175,6 @@ def halt():
# abort all the threads # abort all the threads
WEBSERVER.stop_tasks()
maintenanceScheduler.abort = True maintenanceScheduler.abort = True
logger.log(u"Waiting for the MAINTENANCE scheduler thread to exit") logger.log(u"Waiting for the MAINTENANCE scheduler thread to exit")
try: try:
@ -1190,6 +1182,13 @@ def halt():
except: except:
pass pass
dailySearchScheduler.abort = True
logger.log(u"Waiting for the DAILYSEARCH thread to exit")
try:
dailySearchScheduler.thread.join(10)
except:
pass
backlogSearchScheduler.abort = True backlogSearchScheduler.abort = True
logger.log(u"Waiting for the BACKLOG thread to exit") logger.log(u"Waiting for the BACKLOG thread to exit")
try: try:
@ -1281,7 +1280,6 @@ def sig_handler(signum=None, frame=None):
logger.log(u"Signal %i caught, saving and exiting..." % int(signum)) logger.log(u"Signal %i caught, saving and exiting..." % int(signum))
saveAndShutdown() saveAndShutdown()
def saveAll(): def saveAll():
global showList global showList
@ -1294,21 +1292,19 @@ def saveAll():
logger.log(u"Saving config file to disk") logger.log(u"Saving config file to disk")
save_config() save_config()
def saveAndShutdown(restart=False): def saveAndShutdown(restart=False):
global WEBSERVER
halt()
saveAll()
logger.log('Shutting down tornado') logger.log('Shutting down tornado')
try: try:
WEBSERVER.stop() IOLoop.current().stop()
except RuntimeError: except RuntimeError:
pass pass
except: except:
logger.log('Failed shutting down the server: %s' % traceback.format_exc(), logger.ERROR) logger.log('Failed shutting down the server: %s' % traceback.format_exc(), logger.ERROR)
halt()
saveAll()
if CREATEPID: if CREATEPID:
logger.log(u"Removing pidfile " + str(PIDFILE)) logger.log(u"Removing pidfile " + str(PIDFILE))
remove_pid_file(PIDFILE) remove_pid_file(PIDFILE)
@ -1341,17 +1337,15 @@ def saveAndShutdown(restart=False):
os._exit(0) os._exit(0)
def invoke_command(to_call, *args, **kwargs): def invoke_command(to_call, *args, **kwargs):
global invoked_command
def delegate(): def delegate():
to_call(*args, **kwargs) to_call(*args, **kwargs)
invoked_command = delegate logger.log(u"Placed invoked command: " + repr(delegate) + " for " + repr(to_call) + " with " + repr(
logger.log(u"Placed invoked command: " + repr(invoked_command) + " for " + repr(to_call) + " with " + repr(
args) + " and " + repr(kwargs), logger.DEBUG) args) + " and " + repr(kwargs), logger.DEBUG)
IOLoop.current().add_callback(delegate)
def invoke_restart(soft=True): def invoke_restart(soft=True):
invoke_command(restart, soft=soft) invoke_command(restart, soft=soft)

View File

@ -1,5 +1,4 @@
import os import os
import datetime
import sickbeard import sickbeard
import webserve import webserve
@ -7,7 +6,6 @@ from sickbeard import logger
from sickbeard.helpers import create_https_certificates from sickbeard.helpers import create_https_certificates
from tornado.web import Application, StaticFileHandler, RedirectHandler, HTTPError from tornado.web import Application, StaticFileHandler, RedirectHandler, HTTPError
from tornado.httpserver import HTTPServer from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
class MultiStaticFileHandler(StaticFileHandler): class MultiStaticFileHandler(StaticFileHandler):
def initialize(self, paths, default_filename=None): def initialize(self, paths, default_filename=None):
@ -29,139 +27,108 @@ class MultiStaticFileHandler(StaticFileHandler):
# Oops file not found anywhere! # Oops file not found anywhere!
raise HTTPError(404) 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 http_error_401_hander(status, message, traceback, version):
def __init__(self, options, cycleTime=datetime.timedelta(seconds=3)): """ 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'''<!DOCTYPE html>
<html>
<head>
<title>%s</title>
</head>
<body>
<br/>
<font color="#0000FF">Error %s: You need to provide a valid username and password.</font>
</body>
</html>
''' % ('Access denied', status)
self.amActive = False def http_error_404_hander(status, message, traceback, version):
self.lastRun = datetime.datetime.fromordinal(1) """ Custom handler for 404 error, redirect back to main page """
self.cycleTime = cycleTime return r'''<!DOCTYPE html>
self.abort = False <html>
<head>
<title>404</title>
<script type="text/javascript" charset="utf-8">
<!--
location.href = "%s/home/"
//-->
</script>
</head>
<body>
<br/>
</body>
</html>
''' % options['web_root']
self.server = None # tornado setup
self.ioloop = None enable_https = options['enable_https']
self.tasks = [] https_cert = options['https_cert']
https_key = options['https_key']
self.options = options if enable_https:
self.options.setdefault('port', 8081) # If either the HTTPS certificate or key do not exist, make some self-signed ones.
self.options.setdefault('host', '0.0.0.0') if not (https_cert and os.path.exists(https_cert)) or not (https_key and os.path.exists(https_key)):
self.options.setdefault('log_dir', None) if not create_https_certificates(https_cert, https_key):
self.options.setdefault('username', '') logger.log(u"Unable to create CERT/KEY files, disabling HTTPS")
self.options.setdefault('password', '')
self.options.setdefault('web_root', '/')
assert isinstance(self.options['port'], int)
assert 'data_root' in self.options
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'''<!DOCTYPE html>
<html>
<head>
<title>%s</title>
</head>
<body>
<br/>
<font color="#0000FF">Error %s: You need to provide a valid username and password.</font>
</body>
</html>
''' % ('Access denied', status)
def http_error_404_hander(status, message, traceback, version):
""" Custom handler for 404 error, redirect back to main page """
return r'''<!DOCTYPE html>
<html>
<head>
<title>404</title>
<script type="text/javascript" charset="utf-8">
<!--
location.href = "%s/home/"
//-->
</script>
</head>
<body>
<br/>
</body>
</html>
''' % self.options['web_root']
# tornado setup
enable_https = self.options['enable_https']
https_cert = self.options['https_cert']
https_key = self.options['https_key']
if enable_https:
# If either the HTTPS certificate or key do not exist, make some self-signed ones.
if not (https_cert and os.path.exists(https_cert)) or not (https_key and os.path.exists(https_key)):
if not create_https_certificates(https_cert, https_key):
logger.log(u"Unable to create CERT/KEY files, disabling HTTPS")
sickbeard.ENABLE_HTTPS = False
enable_https = False
if not (os.path.exists(https_cert) and os.path.exists(https_key)):
logger.log(u"Disabled HTTPS because of missing CERT and KEY files", logger.WARNING)
sickbeard.ENABLE_HTTPS = False sickbeard.ENABLE_HTTPS = False
enable_https = False enable_https = False
# Load the app if not (os.path.exists(https_cert) and os.path.exists(https_key)):
app = Application([], logger.log(u"Disabled HTTPS because of missing CERT and KEY files", logger.WARNING)
log_function=lambda x: None, sickbeard.ENABLE_HTTPS = False
debug=False, enable_https = False
gzip=True,
cookie_secret='61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=',
login_url='/login',
autoreload=True
)
# Index Handler # Load the app
app.add_handlers(".*$", [ app = Application([],
(r"/", RedirectHandler, {'url': '/home/'}), debug=False,
(r'/login', webserve.LoginHandler), gzip=True,
(r'%s(.*)(/?)' % self.options['web_root'], webserve.IndexHandler) cookie_secret='61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=',
]) login_url='/login'
)
# Static Path Handler # Index Handler
app.add_handlers(".*$", [ app.add_handlers(".*$", [
('%s/%s/(.*)([^/]*)' % (self.options['web_root'], 'images'), MultiStaticFileHandler, (r"/", RedirectHandler, {'url': '/home/'}),
{'paths': [os.path.join(self.options['data_root'], 'images'), (r'/login', webserve.LoginHandler),
os.path.join(sickbeard.CACHE_DIR, 'images'), (r'%s(.*)(/?)' % options['web_root'], webserve.IndexHandler)
os.path.join(sickbeard.CACHE_DIR, 'images', 'thumbnails')]}), ])
('%s/%s/(.*)([^/]*)' % (self.options['web_root'], 'css'), MultiStaticFileHandler,
{'paths': [os.path.join(self.options['data_root'], 'css')]}),
('%s/%s/(.*)([^/]*)' % (self.options['web_root'], 'js'), MultiStaticFileHandler,
{'paths': [os.path.join(self.options['data_root'], 'js')]})
]) # Static Path Handler
app.add_handlers(".*$", [
('%s/%s/(.*)([^/]*)' % (options['web_root'], 'images'), MultiStaticFileHandler,
{'paths': [os.path.join(options['data_root'], 'images'),
os.path.join(sickbeard.CACHE_DIR, 'images'),
os.path.join(sickbeard.CACHE_DIR, 'images', 'thumbnails')]}),
('%s/%s/(.*)([^/]*)' % (options['web_root'], 'css'), MultiStaticFileHandler,
{'paths': [os.path.join(options['data_root'], 'css')]}),
('%s/%s/(.*)([^/]*)' % (options['web_root'], 'js'), MultiStaticFileHandler,
{'paths': [os.path.join(options['data_root'], 'js')]})
if enable_https: ])
protocol = "https"
self.server = HTTPServer(app, no_keep_alive=True,
ssl_options={"certfile": https_cert, "keyfile": https_key})
else:
protocol = "http"
self.server = HTTPServer(app, no_keep_alive=True)
logger.log(u"Starting SickRage on " + protocol + "://" + str(self.options['host']) + ":" + str( global server
self.options['port']) + "/")
self.ioloop = IOLoop.current() if enable_https:
protocol = "https"
server = HTTPServer(app, no_keep_alive=True,
ssl_options={"certfile": https_cert, "keyfile": https_key})
else:
protocol = "http"
server = HTTPServer(app, no_keep_alive=True)
def start(self): logger.log(u"Starting SickRage on " + protocol + "://" + str(options['host']) + ":" + str(
self.server.listen(self.options['port'], self.options['host']) options['port']) + "/")
self.ioloop.start()
def stop(self): server.listen(options['port'], options['host'])
self.ioloop.stop()
def close(self):
self.ioloop.close()
def start_tasks(self):
for task in self.tasks:
task.start()
def stop_tasks(self):
for task in self.tasks:
task.stop()