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:
parent
fa01711192
commit
7d52d079fa
34
SickBeard.py
34
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__":
|
||||
|
@ -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)
|
||||
|
@ -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'])
|
Loading…
Reference in New Issue
Block a user