summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--bazarr.py21
-rw-r--r--bazarr/app/database.py10
-rw-r--r--bazarr/app/server.py55
-rw-r--r--bazarr/app/signalr_client.py10
-rw-r--r--bazarr/init.py2
-rw-r--r--bazarr/main.py12
-rw-r--r--requirements.txt1
7 files changed, 64 insertions, 47 deletions
diff --git a/bazarr.py b/bazarr.py
index e0f214f93..f5fc76bb8 100644
--- a/bazarr.py
+++ b/bazarr.py
@@ -52,22 +52,27 @@ dir_name = os.path.dirname(__file__)
def end_child_process(ep):
try:
- ep.kill()
+ if os.name != 'nt':
+ try:
+ ep.send_signal(signal.SIGINT)
+ except ProcessLookupError:
+ pass
+ else:
+ import win32api
+ import win32con
+ try:
+ win32api.GenerateConsoleCtrlEvent(win32con.CTRL_C_EVENT, ep.pid)
+ except KeyboardInterrupt:
+ pass
except:
- pass
-
-def terminate_child_process(ep):
- try:
ep.terminate()
- except:
- pass
def start_bazarr():
script = [get_python_path(), "-u", os.path.normcase(os.path.join(dir_name, 'bazarr', 'main.py'))] + sys.argv[1:]
ep = subprocess.Popen(script, stdout=None, stderr=None, stdin=subprocess.DEVNULL)
atexit.register(end_child_process, ep=ep)
- signal.signal(signal.SIGTERM, lambda signal_no, frame: terminate_child_process(ep))
+ signal.signal(signal.SIGTERM, lambda signal_no, frame: end_child_process(ep))
def check_status():
diff --git a/bazarr/app/database.py b/bazarr/app/database.py
index 690bda40b..c2a97987d 100644
--- a/bazarr/app/database.py
+++ b/bazarr/app/database.py
@@ -5,6 +5,7 @@ import json
import logging
import os
import flask_migrate
+import signal
from dogpile.cache import make_region
from datetime import datetime
@@ -12,7 +13,7 @@ from datetime import datetime
from sqlalchemy import create_engine, inspect, DateTime, ForeignKey, Integer, LargeBinary, Text, func, text, BigInteger
# importing here to be indirectly imported in other modules later
from sqlalchemy import update, delete, select, func # noqa W0611
-from sqlalchemy.orm import scoped_session, sessionmaker, mapped_column
+from sqlalchemy.orm import scoped_session, sessionmaker, mapped_column, close_all_sessions
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.pool import NullPool
@@ -74,11 +75,18 @@ session_factory = sessionmaker(bind=engine)
database = scoped_session(session_factory)
+def close_database():
+ close_all_sessions()
+ engine.dispose()
+
+
@atexit.register
def _stop_worker_threads():
database.remove()
+signal.signal(signal.SIGTERM, lambda signal_no, frame: close_database())
+
Base = declarative_base()
metadata = Base.metadata
diff --git a/bazarr/app/server.py b/bazarr/app/server.py
index 48db3912a..52d711fbe 100644
--- a/bazarr/app/server.py
+++ b/bazarr/app/server.py
@@ -13,7 +13,7 @@ from api import api_bp
from .ui import ui_bp
from .get_args import args
from .config import settings, base_url
-from .database import database
+from .database import close_database
from .app import create_app
app = create_app()
@@ -63,49 +63,40 @@ class Server:
self.shutdown()
def start(self):
+ logging.info(f'BAZARR is started and waiting for request on http://{self.server.effective_host}:'
+ f'{self.server.effective_port}')
try:
- logging.info(f'BAZARR is started and waiting for request on http://{self.server.effective_host}:'
- f'{self.server.effective_port}')
- try:
- self.server.run()
- except Exception:
- pass
- except KeyboardInterrupt:
+ self.server.run()
+ except (KeyboardInterrupt, SystemExit):
self.shutdown()
+ except Exception:
+ pass
def shutdown(self):
try:
- self.server.close()
+ stop_file = io.open(os.path.join(args.config_dir, "bazarr.stop"), "w", encoding='UTF-8')
except Exception as e:
- logging.error(f'BAZARR Cannot stop Waitress: {repr(e)}')
+ logging.error(f'BAZARR Cannot create stop file: {repr(e)}')
else:
- database.close()
- try:
- stop_file = io.open(os.path.join(args.config_dir, "bazarr.stop"), "w", encoding='UTF-8')
- except Exception as e:
- logging.error(f'BAZARR Cannot create stop file: {repr(e)}')
- else:
- logging.info('Bazarr is being shutdown...')
- stop_file.write(str(''))
- stop_file.close()
- os._exit(0)
+ logging.info('Bazarr is being shutdown...')
+ stop_file.write(str(''))
+ stop_file.close()
+ close_database()
+ self.server.close()
+ os._exit(0)
def restart(self):
try:
- self.server.close()
+ restart_file = io.open(os.path.join(args.config_dir, "bazarr.restart"), "w", encoding='UTF-8')
except Exception as e:
- logging.error(f'BAZARR Cannot stop Waitress: {repr(e)}')
+ logging.error(f'BAZARR Cannot create restart file: {repr(e)}')
else:
- database.close()
- try:
- restart_file = io.open(os.path.join(args.config_dir, "bazarr.restart"), "w", encoding='UTF-8')
- except Exception as e:
- logging.error(f'BAZARR Cannot create restart file: {repr(e)}')
- else:
- logging.info('Bazarr is being restarted...')
- restart_file.write(str(''))
- restart_file.close()
- os._exit(0)
+ logging.info('Bazarr is being restarted...')
+ restart_file.write(str(''))
+ restart_file.close()
+ close_database()
+ self.server.close()
+ os._exit(0)
webserver = Server()
diff --git a/bazarr/app/signalr_client.py b/bazarr/app/signalr_client.py
index 2f048eb17..b731e09e8 100644
--- a/bazarr/app/signalr_client.py
+++ b/bazarr/app/signalr_client.py
@@ -340,14 +340,20 @@ def consume_queue(queue):
data = queue.popleft()
except IndexError:
pass
+ except (KeyboardInterrupt, SystemExit):
+ break
else:
dispatcher(data)
sleep(0.1)
# start both queue consuming threads
-threading.Thread(target=consume_queue, args=(sonarr_queue,)).start()
-threading.Thread(target=consume_queue, args=(radarr_queue,)).start()
+sonarr_queue_thread = threading.Thread(target=consume_queue, args=(sonarr_queue,))
+sonarr_queue_thread.daemon = True
+sonarr_queue_thread.start()
+radarr_queue_thread = threading.Thread(target=consume_queue, args=(radarr_queue,))
+radarr_queue_thread.daemon = True
+radarr_queue_thread.start()
# instantiate proper SignalR client
sonarr_signalr_client = SonarrSignalrClientLegacy() if get_sonarr_info.version().startswith(('0.', '2.', '3.')) else \
diff --git a/bazarr/init.py b/bazarr/init.py
index 9db2b73ef..0a2496df0 100644
--- a/bazarr/init.py
+++ b/bazarr/init.py
@@ -77,6 +77,8 @@ def is_virtualenv():
# deploy requirements.txt
if not args.no_update:
try:
+ if os.name == 'nt':
+ import win32api, win32con # noqa E401
import lxml, numpy, webrtcvad, setuptools, PIL # noqa E401
except ImportError:
try:
diff --git a/bazarr/main.py b/bazarr/main.py
index 970684d14..c2650aed7 100644
--- a/bazarr/main.py
+++ b/bazarr/main.py
@@ -1,8 +1,6 @@
# coding=utf-8
import os
-import io
-import logging
from threading import Thread
@@ -75,9 +73,15 @@ update_notifier()
if not args.no_signalr:
if settings.general.use_sonarr:
- Thread(target=sonarr_signalr_client.start).start()
+ sonarr_signalr_thread = Thread(target=sonarr_signalr_client.start)
+ sonarr_signalr_thread.daemon = True
+ sonarr_signalr_thread.start()
+ sonarr_signalr_thread.join()
if settings.general.use_radarr:
- Thread(target=radarr_signalr_client.start).start()
+ radarr_signalr_thread = Thread(target=radarr_signalr_client.start)
+ radarr_signalr_thread.daemon = True
+ radarr_signalr_thread.start()
+ radarr_signalr_thread.join()
if __name__ == "__main__":
diff --git a/requirements.txt b/requirements.txt
index 7e40a4347..469b8808b 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -3,3 +3,4 @@ lxml>=4.3.0, <5.0.0
numpy>=1.12.0
webrtcvad-wheels>=2.0.10
Pillow>=9.0.0 --only-binary=Pillow
+pywin32; platform_system == "Windows"