1
0
Fork 0
mirror of https://github.com/morpheus65535/bazarr synced 2024-12-21 23:32:31 +00:00

Fixed improper closing of resources on exit

This commit is contained in:
morpheus65535 2024-01-10 23:04:23 -05:00 committed by GitHub
parent c17d127323
commit 0807bd99b9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 64 additions and 47 deletions

View file

@ -52,22 +52,27 @@ dir_name = os.path.dirname(__file__)
def end_child_process(ep): def end_child_process(ep):
try: 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: except:
pass
def terminate_child_process(ep):
try:
ep.terminate() ep.terminate()
except:
pass
def start_bazarr(): def start_bazarr():
script = [get_python_path(), "-u", os.path.normcase(os.path.join(dir_name, 'bazarr', 'main.py'))] + sys.argv[1:] 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) ep = subprocess.Popen(script, stdout=None, stderr=None, stdin=subprocess.DEVNULL)
atexit.register(end_child_process, ep=ep) 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(): def check_status():

View file

@ -5,6 +5,7 @@ import json
import logging import logging
import os import os
import flask_migrate import flask_migrate
import signal
from dogpile.cache import make_region from dogpile.cache import make_region
from datetime import datetime 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 from sqlalchemy import create_engine, inspect, DateTime, ForeignKey, Integer, LargeBinary, Text, func, text, BigInteger
# importing here to be indirectly imported in other modules later # importing here to be indirectly imported in other modules later
from sqlalchemy import update, delete, select, func # noqa W0611 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.ext.declarative import declarative_base
from sqlalchemy.pool import NullPool from sqlalchemy.pool import NullPool
@ -74,11 +75,18 @@ session_factory = sessionmaker(bind=engine)
database = scoped_session(session_factory) database = scoped_session(session_factory)
def close_database():
close_all_sessions()
engine.dispose()
@atexit.register @atexit.register
def _stop_worker_threads(): def _stop_worker_threads():
database.remove() database.remove()
signal.signal(signal.SIGTERM, lambda signal_no, frame: close_database())
Base = declarative_base() Base = declarative_base()
metadata = Base.metadata metadata = Base.metadata

View file

@ -13,7 +13,7 @@ from api import api_bp
from .ui import ui_bp from .ui import ui_bp
from .get_args import args from .get_args import args
from .config import settings, base_url from .config import settings, base_url
from .database import database from .database import close_database
from .app import create_app from .app import create_app
app = create_app() app = create_app()
@ -63,49 +63,40 @@ class Server:
self.shutdown() self.shutdown()
def start(self): 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: try:
logging.info(f'BAZARR is started and waiting for request on http://{self.server.effective_host}:' self.server.run()
f'{self.server.effective_port}') except (KeyboardInterrupt, SystemExit):
try:
self.server.run()
except Exception:
pass
except KeyboardInterrupt:
self.shutdown() self.shutdown()
except Exception:
pass
def shutdown(self): def shutdown(self):
try: try:
self.server.close() stop_file = io.open(os.path.join(args.config_dir, "bazarr.stop"), "w", encoding='UTF-8')
except Exception as e: except Exception as e:
logging.error(f'BAZARR Cannot stop Waitress: {repr(e)}') logging.error(f'BAZARR Cannot create stop file: {repr(e)}')
else: else:
database.close() logging.info('Bazarr is being shutdown...')
try: stop_file.write(str(''))
stop_file = io.open(os.path.join(args.config_dir, "bazarr.stop"), "w", encoding='UTF-8') stop_file.close()
except Exception as e: close_database()
logging.error(f'BAZARR Cannot create stop file: {repr(e)}') self.server.close()
else: os._exit(0)
logging.info('Bazarr is being shutdown...')
stop_file.write(str(''))
stop_file.close()
os._exit(0)
def restart(self): def restart(self):
try: try:
self.server.close() restart_file = io.open(os.path.join(args.config_dir, "bazarr.restart"), "w", encoding='UTF-8')
except Exception as e: except Exception as e:
logging.error(f'BAZARR Cannot stop Waitress: {repr(e)}') logging.error(f'BAZARR Cannot create restart file: {repr(e)}')
else: else:
database.close() logging.info('Bazarr is being restarted...')
try: restart_file.write(str(''))
restart_file = io.open(os.path.join(args.config_dir, "bazarr.restart"), "w", encoding='UTF-8') restart_file.close()
except Exception as e: close_database()
logging.error(f'BAZARR Cannot create restart file: {repr(e)}') self.server.close()
else: os._exit(0)
logging.info('Bazarr is being restarted...')
restart_file.write(str(''))
restart_file.close()
os._exit(0)
webserver = Server() webserver = Server()

View file

@ -340,14 +340,20 @@ def consume_queue(queue):
data = queue.popleft() data = queue.popleft()
except IndexError: except IndexError:
pass pass
except (KeyboardInterrupt, SystemExit):
break
else: else:
dispatcher(data) dispatcher(data)
sleep(0.1) sleep(0.1)
# start both queue consuming threads # start both queue consuming threads
threading.Thread(target=consume_queue, args=(sonarr_queue,)).start() sonarr_queue_thread = threading.Thread(target=consume_queue, args=(sonarr_queue,))
threading.Thread(target=consume_queue, args=(radarr_queue,)).start() 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 # instantiate proper SignalR client
sonarr_signalr_client = SonarrSignalrClientLegacy() if get_sonarr_info.version().startswith(('0.', '2.', '3.')) else \ sonarr_signalr_client = SonarrSignalrClientLegacy() if get_sonarr_info.version().startswith(('0.', '2.', '3.')) else \

View file

@ -77,6 +77,8 @@ def is_virtualenv():
# deploy requirements.txt # deploy requirements.txt
if not args.no_update: if not args.no_update:
try: try:
if os.name == 'nt':
import win32api, win32con # noqa E401
import lxml, numpy, webrtcvad, setuptools, PIL # noqa E401 import lxml, numpy, webrtcvad, setuptools, PIL # noqa E401
except ImportError: except ImportError:
try: try:

View file

@ -1,8 +1,6 @@
# coding=utf-8 # coding=utf-8
import os import os
import io
import logging
from threading import Thread from threading import Thread
@ -75,9 +73,15 @@ update_notifier()
if not args.no_signalr: if not args.no_signalr:
if settings.general.use_sonarr: 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: 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__": if __name__ == "__main__":

View file

@ -3,3 +3,4 @@ lxml>=4.3.0, <5.0.0
numpy>=1.12.0 numpy>=1.12.0
webrtcvad-wheels>=2.0.10 webrtcvad-wheels>=2.0.10
Pillow>=9.0.0 --only-binary=Pillow Pillow>=9.0.0 --only-binary=Pillow
pywin32; platform_system == "Windows"