diff --git a/CouchPotato.py b/CouchPotato.py index f5b9c046..7049cda5 100755 --- a/CouchPotato.py +++ b/CouchPotato.py @@ -72,10 +72,11 @@ class Loader(object): signal.signal(signal.SIGTERM, lambda signum, stack_frame: sys.exit(1)) from couchpotato.core.event import addEvent - addEvent('app.after_shutdown', self.afterShutdown) + addEvent('app.do_shutdown', self.setRestart) - def afterShutdown(self, restart): + def setRestart(self, restart): self.do_restart = restart + return True def onExit(self, signal, frame): from couchpotato.core.event import fireEvent @@ -103,7 +104,6 @@ class Loader(object): # Release log files and shutdown logger logging.shutdown() - time.sleep(3) args = [sys.executable] + [os.path.join(base_path, os.path.basename(__file__))] + sys.argv[1:] subprocess.Popen(args) diff --git a/couchpotato/api.py b/couchpotato/api.py index 17942583..99a2c6ad 100644 --- a/couchpotato/api.py +++ b/couchpotato/api.py @@ -91,6 +91,10 @@ class ApiHandler(RequestHandler): self.write('API call doesn\'t seem to exist') return + # Create lock if it doesn't exist + if route in api_locks and not api_locks.get(route): + api_locks[route] = threading.Lock() + api_locks[route].acquire() try: diff --git a/couchpotato/core/_base/_core.py b/couchpotato/core/_base/_core.py index 1171478d..852c42c2 100644 --- a/couchpotato/core/_base/_core.py +++ b/couchpotato/core/_base/_core.py @@ -118,7 +118,7 @@ class Core(Plugin): self.shutdown_started = True - fireEvent('app.do_shutdown') + fireEvent('app.do_shutdown', restart = restart) log.debug('Every plugin got shutdown event') loop = True @@ -143,9 +143,11 @@ class Core(Plugin): log.debug('Safe to shutdown/restart') + loop = IOLoop.current() + try: - if not IOLoop.current()._closing: - IOLoop.current().stop() + if not loop._closing: + loop.stop() except RuntimeError: pass except: diff --git a/couchpotato/core/_base/scheduler.py b/couchpotato/core/_base/scheduler.py index 16a3a4f2..271a2d81 100644 --- a/couchpotato/core/_base/scheduler.py +++ b/couchpotato/core/_base/scheduler.py @@ -33,9 +33,9 @@ class Scheduler(Plugin): except: pass - def doShutdown(self): + def doShutdown(self, *args, **kwargs): self.stop() - return super(Scheduler, self).doShutdown() + return super(Scheduler, self).doShutdown(*args, **kwargs) def stop(self): if self.started: diff --git a/couchpotato/core/_base/updater/main.py b/couchpotato/core/_base/updater/main.py index 093977da..9f6613ab 100644 --- a/couchpotato/core/_base/updater/main.py +++ b/couchpotato/core/_base/updater/main.py @@ -142,11 +142,11 @@ class Updater(Plugin): 'success': success } - def doShutdown(self): + def doShutdown(self, *args, **kwargs): if not Env.get('dev'): removePyc(Env.get('app_dir'), show_logs = False) - return super(Updater, self).doShutdown() + return super(Updater, self).doShutdown(*args, **kwargs) class BaseUpdater(Plugin): diff --git a/couchpotato/core/media/_base/media/main.py b/couchpotato/core/media/_base/media/main.py index 1340aa6a..1e882d15 100644 --- a/couchpotato/core/media/_base/media/main.py +++ b/couchpotato/core/media/_base/media/main.py @@ -454,17 +454,20 @@ class MediaPlugin(MediaBase): else: move_to_wanted = True - profile = db.get('id', m['profile_id']) - media_releases = fireEvent('release.for_media', m['_id'], single = True) + try: + profile = db.get('id', m['profile_id']) + media_releases = fireEvent('release.for_media', m['_id'], single = True) - for q_identifier in profile['qualities']: - index = profile['qualities'].index(q_identifier) + for q_identifier in profile['qualities']: + index = profile['qualities'].index(q_identifier) - for release in media_releases: - if q_identifier == release['quality'] and (release.get('status') == 'done' and profile['finish'][index]): - move_to_wanted = False + for release in media_releases: + if q_identifier == release['quality'] and (release.get('status') == 'done' and profile['finish'][index]): + move_to_wanted = False - m['status'] = 'active' if move_to_wanted else 'done' + m['status'] = 'active' if move_to_wanted else 'done' + except RecordNotFound: + log.debug('Failed restatus: %s', traceback.format_exc()) # Only update when status has changed if previous_status != m['status']: diff --git a/couchpotato/core/notifications/core/static/notification.js b/couchpotato/core/notifications/core/static/notification.js index 81bf9500..93bfa15d 100644 --- a/couchpotato/core/notifications/core/static/notification.js +++ b/couchpotato/core/notifications/core/static/notification.js @@ -122,9 +122,12 @@ var NotificationBase = new Class({ startPoll: function(){ var self = this; - if(self.stopped || (self.request && self.request.isRunning())) + if(self.stopped) return; + if(self.request && self.request.isRunning()) + self.request.cancel(); + self.request = Api.request('nonblock/notification.listener', { 'onSuccess': function(json){ self.processData(json, false) @@ -149,7 +152,7 @@ var NotificationBase = new Class({ var self = this; // Process data - if(json){ + if(json && json.result){ Array.each(json.result, function(result){ App.trigger(result._t || result.type, [result]); if(result.message && result.read === undefined && !init) diff --git a/couchpotato/core/plugins/base.py b/couchpotato/core/plugins/base.py index ac5ca87e..bc66123f 100644 --- a/couchpotato/core/plugins/base.py +++ b/couchpotato/core/plugins/base.py @@ -263,7 +263,7 @@ class Plugin(object): def afterCall(self, handler): self.isRunning('%s.%s' % (self.getName(), handler.__name__), False) - def doShutdown(self): + def doShutdown(self, *args, **kwargs): self.shuttingDown(True) return True diff --git a/couchpotato/runner.py b/couchpotato/runner.py index b2b918a6..3a779ba2 100644 --- a/couchpotato/runner.py +++ b/couchpotato/runner.py @@ -277,22 +277,23 @@ def runCouchPotato(options, base_path, args, data_dir = None, log_dir = None, En loop = IOLoop.current() # Reload hook - def test(): + def reload_hook(): fireEvent('app.shutdown') - add_reload_hook(test) + add_reload_hook(reload_hook) # Some logging and fire load event try: log.info('Starting server on port %(port)s', config) except: pass fireEventAsync('app.load') + ssl_options = None if config['ssl_cert'] and config['ssl_key']: - server = HTTPServer(application, no_keep_alive = True, ssl_options = { + ssl_options = { 'certfile': config['ssl_cert'], 'keyfile': config['ssl_key'], - }) - else: - server = HTTPServer(application, no_keep_alive = True) + } + + server = HTTPServer(application, no_keep_alive = True) try_restart = True restart_tries = 5 @@ -301,6 +302,9 @@ def runCouchPotato(options, base_path, args, data_dir = None, log_dir = None, En try: server.listen(config['port'], config['host']) loop.start() + server.close_all_connections() + server.stop() + loop.close(all_fds = True) except Exception as e: log.error('Failed starting: %s', traceback.format_exc()) try: @@ -314,6 +318,8 @@ def runCouchPotato(options, base_path, args, data_dir = None, log_dir = None, En continue else: return + except ValueError: + return except: pass diff --git a/couchpotato/static/scripts/couchpotato.js b/couchpotato/static/scripts/couchpotato.js index b71c1f0d..19b9f455 100644 --- a/couchpotato/static/scripts/couchpotato.js +++ b/couchpotato/static/scripts/couchpotato.js @@ -272,11 +272,18 @@ (function(){ - Api.request('app.available', { - 'onFailure': function(){ - self.checkAvailable.delay(1000, self, [delay, onAvailable]); - self.fireEvent('unload'); + var onFailure = function(){ + self.checkAvailable.delay(1000, self, [delay, onAvailable]); + self.fireEvent('unload'); + } + + var request = Api.request('app.available', { + 'timeout': 2000, + 'onTimeout': function(){ + request.cancel(); + onFailure(); }, + 'onFailure': onFailure, 'onSuccess': function(){ if(onAvailable) onAvailable();