1
0
mirror of https://github.com/moparisthebest/SickRage synced 2024-12-13 11:32:20 -05: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
webserveInit.initWebServer(options)
# Build from the DB to start with # Build from the DB to start with
logger.log(u"Loading initial show list") logger.log(u"Loading initial show list")
loadShowsFromDB() 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,28 +27,15 @@ class MultiStaticFileHandler(StaticFileHandler):
# Oops file not found anywhere! # Oops file not found anywhere!
raise HTTPError(404) raise HTTPError(404)
def initWebServer(options={}):
class webserverInit(): options.setdefault('port', 8081)
def __init__(self, options, cycleTime=datetime.timedelta(seconds=3)): options.setdefault('host', '0.0.0.0')
options.setdefault('log_dir', None)
self.amActive = False options.setdefault('username', '')
self.lastRun = datetime.datetime.fromordinal(1) options.setdefault('password', '')
self.cycleTime = cycleTime options.setdefault('web_root', '/')
self.abort = False assert isinstance(options['port'], int)
assert 'data_root' in options
self.server = None
self.ioloop = None
self.tasks = []
self.options = options
self.options.setdefault('port', 8081)
self.options.setdefault('host', '0.0.0.0')
self.options.setdefault('log_dir', None)
self.options.setdefault('username', '')
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): def http_error_401_hander(status, message, traceback, version):
""" Custom handler for 401 error """ """ Custom handler for 401 error """
@ -58,7 +43,7 @@ class webserverInit():
logger.log(u"Tornado caught an error: %s %s" % (status, message), logger.ERROR) logger.log(u"Tornado caught an error: %s %s" % (status, message), logger.ERROR)
logger.log(traceback, logger.DEBUG) logger.log(traceback, logger.DEBUG)
return r'''<!DOCTYPE html> return r'''<!DOCTYPE html>
<html> <html>
<head> <head>
<title>%s</title> <title>%s</title>
</head> </head>
@ -66,13 +51,13 @@ class webserverInit():
<br/> <br/>
<font color="#0000FF">Error %s: You need to provide a valid username and password.</font> <font color="#0000FF">Error %s: You need to provide a valid username and password.</font>
</body> </body>
</html> </html>
''' % ('Access denied', status) ''' % ('Access denied', status)
def http_error_404_hander(status, message, traceback, version): def http_error_404_hander(status, message, traceback, version):
""" Custom handler for 404 error, redirect back to main page """ """ Custom handler for 404 error, redirect back to main page """
return r'''<!DOCTYPE html> return r'''<!DOCTYPE html>
<html> <html>
<head> <head>
<title>404</title> <title>404</title>
<script type="text/javascript" charset="utf-8"> <script type="text/javascript" charset="utf-8">
@ -84,13 +69,13 @@ class webserverInit():
<body> <body>
<br/> <br/>
</body> </body>
</html> </html>
''' % self.options['web_root'] ''' % options['web_root']
# tornado setup # tornado setup
enable_https = self.options['enable_https'] enable_https = options['enable_https']
https_cert = self.options['https_cert'] https_cert = options['https_cert']
https_key = self.options['https_key'] https_key = options['https_key']
if enable_https: if enable_https:
# If either the HTTPS certificate or key do not exist, make some self-signed ones. # If either the HTTPS certificate or key do not exist, make some self-signed ones.
@ -107,61 +92,43 @@ class webserverInit():
# Load the app # Load the app
app = Application([], app = Application([],
log_function=lambda x: None,
debug=False, debug=False,
gzip=True, gzip=True,
cookie_secret='61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=', cookie_secret='61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=',
login_url='/login', login_url='/login'
autoreload=True
) )
# Index Handler # Index Handler
app.add_handlers(".*$", [ app.add_handlers(".*$", [
(r"/", RedirectHandler, {'url': '/home/'}), (r"/", RedirectHandler, {'url': '/home/'}),
(r'/login', webserve.LoginHandler), (r'/login', webserve.LoginHandler),
(r'%s(.*)(/?)' % self.options['web_root'], webserve.IndexHandler) (r'%s(.*)(/?)' % options['web_root'], webserve.IndexHandler)
]) ])
# Static Path Handler # Static Path Handler
app.add_handlers(".*$", [ app.add_handlers(".*$", [
('%s/%s/(.*)([^/]*)' % (self.options['web_root'], 'images'), MultiStaticFileHandler, ('%s/%s/(.*)([^/]*)' % (options['web_root'], 'images'), MultiStaticFileHandler,
{'paths': [os.path.join(self.options['data_root'], 'images'), {'paths': [os.path.join(options['data_root'], 'images'),
os.path.join(sickbeard.CACHE_DIR, 'images'), os.path.join(sickbeard.CACHE_DIR, 'images'),
os.path.join(sickbeard.CACHE_DIR, 'images', 'thumbnails')]}), os.path.join(sickbeard.CACHE_DIR, 'images', 'thumbnails')]}),
('%s/%s/(.*)([^/]*)' % (self.options['web_root'], 'css'), MultiStaticFileHandler, ('%s/%s/(.*)([^/]*)' % (options['web_root'], 'css'), MultiStaticFileHandler,
{'paths': [os.path.join(self.options['data_root'], 'css')]}), {'paths': [os.path.join(options['data_root'], 'css')]}),
('%s/%s/(.*)([^/]*)' % (self.options['web_root'], 'js'), MultiStaticFileHandler, ('%s/%s/(.*)([^/]*)' % (options['web_root'], 'js'), MultiStaticFileHandler,
{'paths': [os.path.join(self.options['data_root'], 'js')]}) {'paths': [os.path.join(options['data_root'], 'js')]})
]) ])
global server
if enable_https: if enable_https:
protocol = "https" protocol = "https"
self.server = HTTPServer(app, no_keep_alive=True, server = HTTPServer(app, no_keep_alive=True,
ssl_options={"certfile": https_cert, "keyfile": https_key}) ssl_options={"certfile": https_cert, "keyfile": https_key})
else: else:
protocol = "http" protocol = "http"
self.server = HTTPServer(app, no_keep_alive=True) server = HTTPServer(app, no_keep_alive=True)
logger.log(u"Starting SickRage on " + protocol + "://" + str(self.options['host']) + ":" + str( logger.log(u"Starting SickRage on " + protocol + "://" + str(options['host']) + ":" + str(
self.options['port']) + "/") options['port']) + "/")
self.ioloop = IOLoop.current() server.listen(options['port'], options['host'])
def start(self):
self.server.listen(self.options['port'], self.options['host'])
self.ioloop.start()
def stop(self):
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()