1
0
mirror of https://github.com/moparisthebest/SickRage synced 2024-12-12 11:02:21 -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
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__":

View File

@ -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)

View File

@ -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'''<!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
self.lastRun = datetime.datetime.fromordinal(1)
self.cycleTime = cycleTime
self.abort = False
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>
''' % options['web_root']
self.server = None
self.ioloop = None
self.tasks = []
# tornado setup
enable_https = options['enable_https']
https_cert = options['https_cert']
https_key = options['https_key']
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):
""" 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)
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
# Load the app
app = Application([],
log_function=lambda x: None,
debug=False,
gzip=True,
cookie_secret='61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=',
login_url='/login',
autoreload=True
)
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
enable_https = False
# Index Handler
app.add_handlers(".*$", [
(r"/", RedirectHandler, {'url': '/home/'}),
(r'/login', webserve.LoginHandler),
(r'%s(.*)(/?)' % self.options['web_root'], webserve.IndexHandler)
])
# Load the app
app = Application([],
debug=False,
gzip=True,
cookie_secret='61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=',
login_url='/login'
)
# Static Path Handler
app.add_handlers(".*$", [
('%s/%s/(.*)([^/]*)' % (self.options['web_root'], 'images'), MultiStaticFileHandler,
{'paths': [os.path.join(self.options['data_root'], 'images'),
os.path.join(sickbeard.CACHE_DIR, 'images'),
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')]})
# Index Handler
app.add_handlers(".*$", [
(r"/", RedirectHandler, {'url': '/home/'}),
(r'/login', webserve.LoginHandler),
(r'%s(.*)(/?)' % options['web_root'], webserve.IndexHandler)
])
])
# 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(
self.options['port']) + "/")
global server
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):
self.server.listen(self.options['port'], self.options['host'])
self.ioloop.start()
logger.log(u"Starting SickRage on " + protocol + "://" + str(options['host']) + ":" + str(
options['port']) + "/")
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()
server.listen(options['port'], options['host'])