mirror of
https://github.com/SickGear/SickGear.git
synced 2024-12-01 00:43:37 +00:00
Fixed start/restart/shutdown issues including any issues with daemonizing.
This commit is contained in:
parent
130daf7d0a
commit
1fc909299d
6 changed files with 359 additions and 165 deletions
160
SickBeard.py
160
SickBeard.py
|
@ -19,7 +19,6 @@
|
|||
|
||||
# Check needed software dependencies to nudge users to fix their setup
|
||||
from __future__ import with_statement
|
||||
import functools
|
||||
|
||||
import sys
|
||||
import shutil
|
||||
|
@ -66,14 +65,21 @@ from sickbeard.databases.mainDB import MIN_DB_VERSION
|
|||
from sickbeard.databases.mainDB import MAX_DB_VERSION
|
||||
|
||||
from lib.configobj import ConfigObj
|
||||
|
||||
from tornado.ioloop import IOLoop
|
||||
from daemon import Daemon
|
||||
|
||||
signal.signal(signal.SIGINT, sickbeard.sig_handler)
|
||||
signal.signal(signal.SIGTERM, sickbeard.sig_handler)
|
||||
|
||||
throwaway = datetime.datetime.strptime('20110101', '%Y%m%d')
|
||||
|
||||
restart = False
|
||||
daemon = None
|
||||
startPort = None
|
||||
forceUpdate = None
|
||||
noLaunch = None
|
||||
web_options = None
|
||||
|
||||
def loadShowsFromDB():
|
||||
"""
|
||||
Populates the showList with shows from the database
|
||||
|
@ -91,48 +97,11 @@ def loadShowsFromDB():
|
|||
sickbeard.showList.append(curShow)
|
||||
except Exception, e:
|
||||
logger.log(
|
||||
u"There was an error creating the show in " + sqlShow["location"] + ": " + str(e).decode('utf-8'),
|
||||
u"There was an error creating the show in " + sqlShow["location"] + ": " + str(e).decode('utf-8'),
|
||||
logger.ERROR)
|
||||
logger.log(traceback.format_exc(), logger.DEBUG)
|
||||
|
||||
# TODO: update the existing shows if the showlist has something in it
|
||||
|
||||
def daemonize():
|
||||
try:
|
||||
pid = os.fork()
|
||||
if pid > 0:
|
||||
sys.exit(0)
|
||||
except OSError:
|
||||
print "fork() failed"
|
||||
sys.exit(1)
|
||||
|
||||
os.chdir(sickbeard.PROG_DIR)
|
||||
os.setsid()
|
||||
# Make sure I can read my own files and shut out others
|
||||
prev= os.umask(0)
|
||||
os.umask(prev and int('077',8))
|
||||
|
||||
try:
|
||||
pid = os.fork()
|
||||
if pid > 0:
|
||||
sys.exit(0)
|
||||
except OSError:
|
||||
print "fork() failed"
|
||||
sys.exit(1)
|
||||
|
||||
# Write pid
|
||||
if sickbeard.CREATEPID:
|
||||
pid = str(os.getpid())
|
||||
logger.log(u"Writing PID: " + pid + " to " + str(sickbeard.PIDFILE))
|
||||
try:
|
||||
file(sickbeard.PIDFILE, 'w').write("%s\n" % pid)
|
||||
except IOError, e:
|
||||
logger.log_error_and_exit(
|
||||
u"Unable to write PID file: " + sickbeard.PIDFILE + " Error: " + str(e.strerror) + " [" + str(
|
||||
e.errno) + "]")
|
||||
|
||||
dev_null = file('/dev/null', 'r')
|
||||
os.dup2(dev_null.fileno(), sys.stdin.fileno())
|
||||
# TODO: update the existing shows if the showlist has something in it
|
||||
|
||||
def restore(srcDir, dstDir):
|
||||
try:
|
||||
|
@ -153,6 +122,8 @@ def main():
|
|||
TV for me
|
||||
"""
|
||||
|
||||
global daemon, startPort, forceUpdate, noLaunch, web_options
|
||||
|
||||
# do some preliminary stuff
|
||||
sickbeard.MY_FULLNAME = os.path.normpath(os.path.abspath(__file__))
|
||||
sickbeard.MY_NAME = os.path.basename(sickbeard.MY_FULLNAME)
|
||||
|
@ -255,7 +226,7 @@ def main():
|
|||
sys.exit("PID file: " + sickbeard.PIDFILE + " already exists. Exiting.")
|
||||
|
||||
# The pidfile is only useful in daemon mode, make sure we can write the file properly
|
||||
if sickbeard.CREATEPID and not sickbeard.restarted:
|
||||
if sickbeard.CREATEPID:
|
||||
if sickbeard.DAEMON:
|
||||
pid_dir = os.path.dirname(sickbeard.PIDFILE)
|
||||
if not os.access(pid_dir, os.F_OK):
|
||||
|
@ -289,7 +260,8 @@ def main():
|
|||
if os.path.isfile(sickbeard.CONFIG_FILE):
|
||||
raise SystemExit("Config file '" + sickbeard.CONFIG_FILE + "' must be writeable.")
|
||||
elif not os.access(os.path.dirname(sickbeard.CONFIG_FILE), os.W_OK):
|
||||
raise SystemExit("Config file root dir '" + os.path.dirname(sickbeard.CONFIG_FILE) + "' must be writeable.")
|
||||
raise SystemExit(
|
||||
"Config file root dir '" + os.path.dirname(sickbeard.CONFIG_FILE) + "' must be writeable.")
|
||||
|
||||
# Check if we need to perform a restore first
|
||||
restoreDir = os.path.join(sickbeard.DATA_DIR, 'restore')
|
||||
|
@ -327,12 +299,6 @@ def main():
|
|||
# Initialize the config and our threads
|
||||
sickbeard.initialize(consoleLogging=consoleLogging)
|
||||
|
||||
if sickbeard.DAEMON:
|
||||
daemonize()
|
||||
|
||||
# Use this PID for everything
|
||||
sickbeard.PID = os.getpid()
|
||||
|
||||
if forcedPort:
|
||||
logger.log(u"Forcing web server to port " + str(forcedPort))
|
||||
startPort = forcedPort
|
||||
|
@ -354,7 +320,8 @@ def main():
|
|||
else:
|
||||
webhost = '0.0.0.0'
|
||||
|
||||
options = {
|
||||
# web server options
|
||||
web_options = {
|
||||
'port': int(startPort),
|
||||
'host': webhost,
|
||||
'data_root': os.path.join(sickbeard.PROG_DIR, 'gui', sickbeard.GUI_NAME),
|
||||
|
@ -366,62 +333,71 @@ def main():
|
|||
'handle_reverse_proxy': sickbeard.HANDLE_REVERSE_PROXY,
|
||||
'https_cert': sickbeard.HTTPS_CERT,
|
||||
'https_key': sickbeard.HTTPS_KEY,
|
||||
}
|
||||
}
|
||||
|
||||
# init tornado
|
||||
try:
|
||||
webserveInit.initWebServer(options)
|
||||
except IOError:
|
||||
logger.log(u"Unable to start web server, is something else running on port %d?" % startPort, logger.ERROR)
|
||||
if sickbeard.LAUNCH_BROWSER and not sickbeard.DAEMON:
|
||||
logger.log(u"Launching browser and exiting", logger.ERROR)
|
||||
# Start SickRage
|
||||
if daemon and daemon.is_running():
|
||||
daemon.restart(daemonize=sickbeard.DAEMON)
|
||||
else:
|
||||
daemon = SickRage(sickbeard.PIDFILE)
|
||||
daemon.start(daemonize=sickbeard.DAEMON)
|
||||
|
||||
class SickRage(Daemon):
|
||||
def run(self):
|
||||
global restart, startPort, forceUpdate, noLaunch, web_options
|
||||
|
||||
# Use this PID for everything
|
||||
sickbeard.PID = os.getpid()
|
||||
|
||||
try:
|
||||
webserveInit.initWebServer(web_options)
|
||||
except IOError:
|
||||
logger.log(u"Unable to start web server, is something else running on port %d?" % startPort, logger.ERROR)
|
||||
if sickbeard.LAUNCH_BROWSER and not sickbeard.DAEMON:
|
||||
logger.log(u"Launching browser and exiting", logger.ERROR)
|
||||
sickbeard.launchBrowser(startPort)
|
||||
sys.exit()
|
||||
|
||||
# Build from the DB to start with
|
||||
loadShowsFromDB()
|
||||
|
||||
# Fire up all our threads
|
||||
sickbeard.start()
|
||||
|
||||
# Launch browser if we're supposed to
|
||||
if sickbeard.LAUNCH_BROWSER and not noLaunch:
|
||||
sickbeard.launchBrowser(startPort)
|
||||
sys.exit()
|
||||
|
||||
# Build from the DB to start with
|
||||
loadShowsFromDB()
|
||||
# Start an update if we're supposed to
|
||||
if forceUpdate or sickbeard.UPDATE_SHOWS_ON_START:
|
||||
sickbeard.showUpdateScheduler.action.run(force=True) # @UndefinedVariable
|
||||
|
||||
# Fire up all our threads
|
||||
sickbeard.start()
|
||||
if sickbeard.LAUNCH_BROWSER and not (noLaunch or sickbeard.DAEMON or restart):
|
||||
sickbeard.launchBrowser(startPort)
|
||||
|
||||
# Launch browser if we're supposed to
|
||||
if sickbeard.LAUNCH_BROWSER and not noLaunch:
|
||||
sickbeard.launchBrowser(startPort)
|
||||
# reset this if sickrage was restarted
|
||||
restart = False
|
||||
|
||||
# Start an update if we're supposed to
|
||||
if forceUpdate or sickbeard.UPDATE_SHOWS_ON_START:
|
||||
sickbeard.showUpdateScheduler.action.run(force=True) # @UndefinedVariable
|
||||
# start IO loop
|
||||
IOLoop.current().start()
|
||||
|
||||
# If we restarted then unset the restarted flag
|
||||
if sickbeard.restarted:
|
||||
sickbeard.restarted = False
|
||||
# close IO loop
|
||||
IOLoop.current().close(True)
|
||||
|
||||
# IOLoop
|
||||
io_loop = IOLoop.current()
|
||||
# stop all tasks
|
||||
sickbeard.halt()
|
||||
|
||||
# Open browser window
|
||||
if sickbeard.LAUNCH_BROWSER and not (noLaunch or sickbeard.DAEMON or sickbeard.restarted):
|
||||
io_loop.add_timeout(datetime.timedelta(seconds=5), functools.partial(sickbeard.launchBrowser, startPort))
|
||||
|
||||
# Start web server
|
||||
io_loop.start()
|
||||
|
||||
# Save and restart/shutdown
|
||||
sickbeard.saveAndShutdown()
|
||||
# save all shows to DB
|
||||
sickbeard.saveAll()
|
||||
|
||||
if __name__ == "__main__":
|
||||
if sys.hexversion >= 0x020600F0:
|
||||
freeze_support()
|
||||
|
||||
while(True):
|
||||
while(not sickbeard.shutdown):
|
||||
main()
|
||||
|
||||
# check if restart was requested
|
||||
if not sickbeard.restarted:
|
||||
if sickbeard.CREATEPID:
|
||||
logger.log(u"Removing pidfile " + str(sickbeard.PIDFILE))
|
||||
sickbeard.remove_pid_file(sickbeard.PIDFILE)
|
||||
break
|
||||
logger.log("SickRage is restarting, please stand by ...")
|
||||
restart = True
|
||||
|
||||
# restart
|
||||
logger.log("Restarting SickRage, please stand by...")
|
||||
logger.log("Goodbye ...")
|
|
@ -1,30 +1,55 @@
|
|||
if (sbHandleReverseProxy != "False" && sbHandleReverseProxy != 0)
|
||||
// Don't add the port to the url if using reverse proxy
|
||||
if (sbHttpsEnabled != "False" && sbHttpsEnabled != 0)
|
||||
var sb_base_url = 'https://'+sbHost+sbRoot;
|
||||
else
|
||||
var sb_base_url = 'http://'+sbHost+sbRoot;
|
||||
else
|
||||
if (sbHttpsEnabled != "False" && sbHttpsEnabled != 0)
|
||||
var sb_base_url = 'https://'+sbHost+':'+sbHttpPort+sbRoot;
|
||||
else
|
||||
var sb_base_url = 'http://'+sbHost+':'+sbHttpPort+sbRoot;
|
||||
if (sbHttpsEnabled != "False" && sbHttpsEnabled != 0) {
|
||||
var sb_base_url = 'https://' + sbHost + ':' + sbHttpPort + sbRoot;
|
||||
} else {
|
||||
var sb_base_url = 'http://' + sbHost + ':' + sbHttpPort + sbRoot;
|
||||
}
|
||||
|
||||
var base_url = window.location.protocol+'//'+window.location.host+sbRoot;
|
||||
var is_alive_url = sbRoot+'/home/is_alive';
|
||||
var base_url = window.location.protocol + '//' + window.location.host + sbRoot;
|
||||
var is_alive_url = sbRoot + '/home/is_alive/';
|
||||
var timeout_id;
|
||||
var restarted = '';
|
||||
var current_pid = '';
|
||||
var num_restart_waits = 0;
|
||||
|
||||
function restartHandler() {
|
||||
function is_alive() {
|
||||
timeout_id = 0;
|
||||
$.get(is_alive_url, function(data) {
|
||||
|
||||
// if it's still initalizing then just wait and try again
|
||||
if (data.msg == 'nope') {
|
||||
$('#shut_down_loading').hide();
|
||||
$('#shut_down_success').show();
|
||||
$('#restart_message').show();
|
||||
setTimeout('is_alive()', 1000);
|
||||
} else {
|
||||
// if this is before we've even shut down then just try again later
|
||||
if (current_pid == '' || data.msg == current_pid) {
|
||||
current_pid = data.msg;
|
||||
setTimeout(is_alive, 1000);
|
||||
|
||||
// if we're ready to go then redirect to new url
|
||||
} else {
|
||||
$('#restart_loading').hide();
|
||||
$('#restart_success').show();
|
||||
$('#refresh_message').show();
|
||||
window.location = sb_base_url + '/home/';
|
||||
}
|
||||
}
|
||||
}, 'jsonp');
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
is_alive();
|
||||
|
||||
$('#shut_down_message').ajaxError(function(e, jqxhr, settings, exception) {
|
||||
num_restart_waits += 1;
|
||||
|
||||
$('#shut_down_loading').hide();
|
||||
$('#shut_down_success').show();
|
||||
$('#restart_message').show();
|
||||
is_alive_url = sb_base_url+'/home/is_alive';
|
||||
is_alive_url = sb_base_url + '/home/is_alive/';
|
||||
|
||||
// if https is enabled or you are currently on https and the port or protocol changed just wait 5 seconds then redirect.
|
||||
// if https is enabled or you are currently on https and the port or protocol changed just wait 5 seconds then redirect.
|
||||
// This is because the ajax will fail if the cert is untrusted or the the http ajax requst from https will fail because of mixed content error.
|
||||
if ((sbHttpsEnabled != "False" && sbHttpsEnabled != 0) || window.location.protocol == "https:") {
|
||||
if (base_url != sb_base_url) {
|
||||
|
@ -34,16 +59,8 @@ function restartHandler() {
|
|||
$('#restart_success').show();
|
||||
$('#refresh_message').show();
|
||||
}, 3000);
|
||||
setTimeout("window.location = sb_base_url+'/home/'", 5000);
|
||||
setTimeout("window.location = sb_base_url + '/home/'", 5000);
|
||||
}
|
||||
} else {
|
||||
timeout_id = 1;
|
||||
setTimeout(function(){
|
||||
$('#restart_loading').hide();
|
||||
$('#restart_success').show();
|
||||
$('#refresh_message').show();
|
||||
}, 3000);
|
||||
setTimeout("window.location = sb_base_url+'/home/'", 5000);
|
||||
}
|
||||
|
||||
// if it is taking forever just give up
|
||||
|
@ -54,34 +71,9 @@ function restartHandler() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (timeout_id == 0)
|
||||
if (timeout_id == 0) {
|
||||
timeout_id = setTimeout('is_alive()', 1000);
|
||||
}
|
||||
|
||||
function is_alive() {
|
||||
timeout_id = 0;
|
||||
|
||||
$.get(is_alive_url, function(data) {
|
||||
|
||||
// if it's still initalizing then just wait and try again
|
||||
if (data.msg == 'nope') {
|
||||
$('#shut_down_loading').hide();
|
||||
$('#shut_down_success').show();
|
||||
$('#restart_message').show();
|
||||
setTimeout('is_alive()', 1000);
|
||||
} else if (data.restarted == 'True') {
|
||||
restartHandler();
|
||||
} else {
|
||||
// if this is before we've even shut down then just try again later
|
||||
if (restarted == '' || data.restarted == restarted) {
|
||||
restarted = data.restarted;
|
||||
setTimeout(is_alive, 1000);
|
||||
}
|
||||
}
|
||||
}, 'jsonp');
|
||||
}
|
||||
});
|
||||
|
||||
$(document).ready(function()
|
||||
{
|
||||
is_alive();
|
||||
});
|
||||
});
|
216
lib/daemon.py
Normal file
216
lib/daemon.py
Normal file
|
@ -0,0 +1,216 @@
|
|||
'''
|
||||
***
|
||||
Modified generic daemon class
|
||||
***
|
||||
|
||||
Author: http://www.jejik.com/articles/2007/02/
|
||||
a_simple_unix_linux_daemon_in_python/www.boxedice.com
|
||||
|
||||
License: http://creativecommons.org/licenses/by-sa/3.0/
|
||||
|
||||
Changes: 23rd Jan 2009 (David Mytton <david@boxedice.com>)
|
||||
- Replaced hard coded '/dev/null in __init__ with os.devnull
|
||||
- Added OS check to conditionally remove code that doesn't
|
||||
work on OS X
|
||||
- Added output to console on completion
|
||||
- Tidied up formatting
|
||||
11th Mar 2009 (David Mytton <david@boxedice.com>)
|
||||
- Fixed problem with daemon exiting on Python 2.4
|
||||
(before SystemExit was part of the Exception base)
|
||||
13th Aug 2010 (David Mytton <david@boxedice.com>
|
||||
- Fixed unhandled exception if PID file is empty
|
||||
'''
|
||||
|
||||
# Core modules
|
||||
import atexit
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import signal
|
||||
|
||||
|
||||
class Daemon(object):
|
||||
"""
|
||||
A generic daemon class.
|
||||
|
||||
Usage: subclass the Daemon class and override the run() method
|
||||
"""
|
||||
def __init__(self, pidfile, stdin=os.devnull,
|
||||
stdout=os.devnull, stderr=os.devnull,
|
||||
home_dir='.', umask=022, verbose=1):
|
||||
self.stdin = stdin
|
||||
self.stdout = stdout
|
||||
self.stderr = stderr
|
||||
self.pidfile = pidfile
|
||||
self.home_dir = home_dir
|
||||
self.verbose = verbose
|
||||
self.umask = umask
|
||||
self.daemon_alive = True
|
||||
|
||||
def daemonize(self):
|
||||
"""
|
||||
Do the UNIX double-fork magic, see Stevens' "Advanced
|
||||
Programming in the UNIX Environment" for details (ISBN 0201563177)
|
||||
http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
|
||||
"""
|
||||
try:
|
||||
pid = os.fork()
|
||||
if pid > 0:
|
||||
# Exit first parent
|
||||
sys.exit(0)
|
||||
except OSError, e:
|
||||
sys.stderr.write(
|
||||
"fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
|
||||
sys.exit(1)
|
||||
|
||||
# Decouple from parent environment
|
||||
os.chdir(self.home_dir)
|
||||
os.setsid()
|
||||
os.umask(self.umask)
|
||||
|
||||
# Do second fork
|
||||
try:
|
||||
pid = os.fork()
|
||||
if pid > 0:
|
||||
# Exit from second parent
|
||||
sys.exit(0)
|
||||
except OSError, e:
|
||||
sys.stderr.write(
|
||||
"fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
|
||||
sys.exit(1)
|
||||
|
||||
if sys.platform != 'darwin': # This block breaks on OS X
|
||||
# Redirect standard file descriptors
|
||||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
si = file(self.stdin, 'r')
|
||||
so = file(self.stdout, 'a+')
|
||||
if self.stderr:
|
||||
se = file(self.stderr, 'a+', 0)
|
||||
else:
|
||||
se = so
|
||||
os.dup2(si.fileno(), sys.stdin.fileno())
|
||||
os.dup2(so.fileno(), sys.stdout.fileno())
|
||||
os.dup2(se.fileno(), sys.stderr.fileno())
|
||||
|
||||
def sigtermhandler(signum, frame):
|
||||
self.daemon_alive = False
|
||||
signal.signal(signal.SIGTERM, sigtermhandler)
|
||||
signal.signal(signal.SIGINT, sigtermhandler)
|
||||
|
||||
if self.verbose >= 1:
|
||||
print "Started"
|
||||
|
||||
# Write pidfile
|
||||
atexit.register(
|
||||
self.delpid) # Make sure pid file is removed if we quit
|
||||
pid = str(os.getpid())
|
||||
file(self.pidfile, 'w+').write("%s\n" % pid)
|
||||
|
||||
def delpid(self):
|
||||
os.remove(self.pidfile)
|
||||
|
||||
def start(self, daemonize=True, *args, **kwargs):
|
||||
"""
|
||||
Start the daemon
|
||||
"""
|
||||
|
||||
if daemonize:
|
||||
if self.verbose >= 1:
|
||||
print "Starting..."
|
||||
|
||||
# Check for a pidfile to see if the daemon already runs
|
||||
try:
|
||||
pf = file(self.pidfile, 'r')
|
||||
pid = int(pf.read().strip())
|
||||
pf.close()
|
||||
except IOError:
|
||||
pid = None
|
||||
except SystemExit:
|
||||
pid = None
|
||||
|
||||
if pid:
|
||||
message = "pidfile %s already exists. Is it already running?\n"
|
||||
sys.stderr.write(message % self.pidfile)
|
||||
sys.exit(1)
|
||||
|
||||
# Start the daemon
|
||||
self.daemonize()
|
||||
|
||||
self.run(*args, **kwargs)
|
||||
|
||||
def stop(self, daemonize=True):
|
||||
"""
|
||||
Stop the daemon
|
||||
"""
|
||||
|
||||
if not daemonize:
|
||||
return
|
||||
|
||||
if self.verbose >= 1:
|
||||
print "Stopping..."
|
||||
|
||||
# Get the pid from the pidfile
|
||||
pid = self.get_pid()
|
||||
|
||||
if not pid:
|
||||
message = "pidfile %s does not exist. Not running?\n"
|
||||
sys.stderr.write(message % self.pidfile)
|
||||
|
||||
# Just to be sure. A ValueError might occur if the PID file is
|
||||
# empty but does actually exist
|
||||
if os.path.exists(self.pidfile):
|
||||
os.remove(self.pidfile)
|
||||
|
||||
return # Not an error in a restart
|
||||
|
||||
# Try killing the daemon process
|
||||
try:
|
||||
i = 0
|
||||
while 1:
|
||||
os.kill(pid, signal.SIGTERM)
|
||||
time.sleep(0.1)
|
||||
i = i + 1
|
||||
if i % 10 == 0:
|
||||
os.kill(pid, signal.SIGHUP)
|
||||
except OSError, err:
|
||||
err = str(err)
|
||||
if err.find("No such process") > 0:
|
||||
if os.path.exists(self.pidfile):
|
||||
os.remove(self.pidfile)
|
||||
else:
|
||||
print str(err)
|
||||
sys.exit(1)
|
||||
|
||||
if self.verbose >= 1:
|
||||
print "Stopped"
|
||||
|
||||
def restart(self, daemonize=True):
|
||||
"""
|
||||
Restart the daemon
|
||||
"""
|
||||
self.stop(daemonize=daemonize)
|
||||
self.start(daemonize=daemonize)
|
||||
|
||||
def get_pid(self):
|
||||
try:
|
||||
pf = file(self.pidfile, 'r')
|
||||
pid = int(pf.read().strip())
|
||||
pf.close()
|
||||
except IOError:
|
||||
pid = None
|
||||
except SystemExit:
|
||||
pid = None
|
||||
return pid
|
||||
|
||||
def is_running(self):
|
||||
pid = self.get_pid()
|
||||
print(pid)
|
||||
return pid and os.path.exists('/proc/%d' % pid)
|
||||
|
||||
def run(self):
|
||||
"""
|
||||
You should override this method when you subclass Daemon.
|
||||
It will be called after the process has been
|
||||
daemonized by start() or restart().
|
||||
"""
|
|
@ -19,7 +19,6 @@
|
|||
from __future__ import with_statement
|
||||
|
||||
import webbrowser
|
||||
import time
|
||||
import datetime
|
||||
import socket
|
||||
import os
|
||||
|
@ -104,7 +103,7 @@ CUR_COMMIT_HASH = None
|
|||
|
||||
INIT_LOCK = Lock()
|
||||
started = False
|
||||
restarted = False
|
||||
shutdown = False
|
||||
|
||||
ACTUAL_LOG_DIR = None
|
||||
LOG_DIR = None
|
||||
|
@ -1284,9 +1283,12 @@ def remove_pid_file(PIDFILE):
|
|||
|
||||
|
||||
def sig_handler(signum=None, frame=None):
|
||||
global shutdown
|
||||
|
||||
if type(signum) != type(None):
|
||||
logger.log(u"Signal %i caught, saving and exiting..." % int(signum))
|
||||
webserveInit.shutdown()
|
||||
shutdown = True
|
||||
IOLoop.current().stop()
|
||||
|
||||
def saveAll():
|
||||
global showList
|
||||
|
@ -1300,10 +1302,24 @@ def saveAll():
|
|||
logger.log(u"Saving config file to disk")
|
||||
save_config()
|
||||
|
||||
def saveAndShutdown():
|
||||
def saveAndShutdown(restart=False):
|
||||
global shutdown
|
||||
|
||||
if not restart:
|
||||
shutdown = True
|
||||
|
||||
# stop tornado web server
|
||||
webserveInit.server.stop()
|
||||
|
||||
# stop all tasks
|
||||
halt()
|
||||
|
||||
# save all shows to db
|
||||
saveAll()
|
||||
|
||||
#stop tornado io loop
|
||||
IOLoop.current().stop()
|
||||
|
||||
def invoke_command(to_call, *args, **kwargs):
|
||||
|
||||
def delegate():
|
||||
|
@ -1319,21 +1335,18 @@ def invoke_restart(soft=True):
|
|||
|
||||
|
||||
def invoke_shutdown():
|
||||
invoke_command(webserveInit.shutdown)
|
||||
|
||||
global shutdown
|
||||
shutdown = True
|
||||
invoke_command(IOLoop.current().stop)
|
||||
|
||||
def restart(soft=True):
|
||||
global restarted
|
||||
|
||||
if soft:
|
||||
halt()
|
||||
saveAll()
|
||||
logger.log(u"Re-initializing all data")
|
||||
initialize()
|
||||
else:
|
||||
restarted=True
|
||||
time.sleep(5)
|
||||
webserveInit.shutdown()
|
||||
IOLoop.current().stop()
|
||||
|
||||
|
||||
def save_config():
|
||||
|
|
|
@ -3099,9 +3099,9 @@ class Home(MainHandler):
|
|||
|
||||
if sickbeard.started:
|
||||
return callback + '(' + json.dumps(
|
||||
{"msg": str(sickbeard.PID), "restarted": str(sickbeard.restarted)}) + ');'
|
||||
{"msg": str(sickbeard.PID)}) + ');'
|
||||
else:
|
||||
return callback + '(' + json.dumps({"msg": "nope", "restarted": str(sickbeard.restarted)}) + ');'
|
||||
return callback + '(' + json.dumps({"msg": "nope"}) + ');'
|
||||
|
||||
|
||||
def index(self, *args, **kwargs):
|
||||
|
@ -3424,7 +3424,6 @@ class Home(MainHandler):
|
|||
|
||||
return _munge(t)
|
||||
|
||||
|
||||
def update(self, pid=None):
|
||||
|
||||
if str(pid) != str(sickbeard.PID):
|
||||
|
|
|
@ -105,16 +105,14 @@ def initWebServer(options={}):
|
|||
logger.log(u"Starting SickRage on " + protocol + "://" + str(options['host']) + ":" + str(
|
||||
options['port']) + "/")
|
||||
|
||||
if not sickbeard.restarted:
|
||||
server.listen(options['port'], options['host'])
|
||||
server.listen(options['port'], options['host'])
|
||||
|
||||
def shutdown():
|
||||
global server
|
||||
|
||||
logger.log('Shutting down tornado io loop')
|
||||
logger.log('Shutting down tornado IO loop')
|
||||
try:
|
||||
IOLoop.current().stop()
|
||||
except RuntimeError:
|
||||
pass
|
||||
except:
|
||||
logger.log('Failed shutting down tornado io loop: %s' % traceback.format_exc(), logger.ERROR)
|
||||
logger.log('Failed shutting down tornado IO loop: %s' % traceback.format_exc(), logger.ERROR)
|
Loading…
Reference in a new issue