From 287f4706d96e08d3d08fc52676c6e7dc759aa2d4 Mon Sep 17 00:00:00 2001 From: Max Value Date: Tue, 10 Dec 2024 02:45:54 +0000 Subject: [PATCH] Fixed improper locking procedure on global id --- critters.py | 73 +++++++++++++++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 33 deletions(-) diff --git a/critters.py b/critters.py index 3472b0c..9168354 100755 --- a/critters.py +++ b/critters.py @@ -6,6 +6,7 @@ from werkzeug.security import generate_password_hash, check_password_hash from werkzeug.middleware.proxy_fix import ProxyFix from multiprocessing import Value from os import listdir +import threading import sqlite3 import random import json @@ -20,9 +21,8 @@ db_keys = ["title", "album", "artist", "year", "link", "info", "category", "play allowed_audio = ["mp3", "wav", "ogg", "flac"] allowed_image = ["png", "jpg", "jpeg"] -current_track_id = Value("I") # This is the global track ID -with current_track_id.get_lock(): - current_track_id.value = 1 +id_lock = threading.Lock() +current_track_id = 1 critters_path = os.environ["CRITTERS_PATH"] audio_path = critters_path + "/audio/" @@ -190,6 +190,7 @@ def admin(): @app.route("/api/next") @auth.login_required def set_current_id(): + global current_track_id server_data = { # The value for each of the keys is the position in the database columns that peice of data can be found "id": 0, # (Note 1) "title": 1, @@ -198,41 +199,42 @@ def set_current_id(): "outtime": 11 } - with current_track_id.get_lock(): # Lock for entire function - track_id = current_track_id.value + with id_lock: + track_id = current_track_id - current_album = "" - current_artist = "" + current_album = "" + current_artist = "" - con = sqlite3.connect(db_path) - cur = con.cursor() - track = cur.execute(f"SELECT album, artist FROM critters WHERE id={track_id}").fetchone() + con = sqlite3.connect(db_path) + cur = con.cursor() + track = cur.execute(f"SELECT album, artist FROM critters WHERE id={track_id}").fetchone() - if track is not None: - current_album, current_artist = track + if track is not None: + current_album, current_artist = track - category_secifier = "" - if "c" in request.args: - category = request.args.get("c") - category_secifier = f" AND category = '{category}'" + category_secifier = "" + if "c" in request.args: + category = request.args.get("c") + category_secifier = f" AND category = '{category}'" - tracks = cur.execute(f""" - SELECT * FROM critters WHERE - playing = 'true' AND - id != {track_id} AND - album != '{current_album}' AND - artist != '{current_artist}'{category_secifier} - """).fetchall() + tracks = cur.execute(f""" + SELECT * FROM critters WHERE + playing = 'true' AND + id != {track_id} AND + album != '{current_album}' AND + artist != '{current_artist}'{category_secifier} + """).fetchall() - if tracks is not None: - target_index = random.randint(0, len(tracks)-1) + if tracks is not None: + target_index = random.randint(0, len(tracks)-1) - current_track_id.value = tracks[target_index][0] + with id_lock: + current_track_id = tracks[target_index][0] - for key, i in server_data.items(): - server_data[key] = tracks[target_index][i] # See note 1 + for key, i in server_data.items(): + server_data[key] = tracks[target_index][i] # See note 1 - return Response(json.dumps(server_data), mimetype="text/json") + return Response(json.dumps(server_data), mimetype="text/json") @app.route("/api/get", methods=['GET']) def get_tracks(): @@ -261,9 +263,11 @@ def get_tracks(): # Call for getting single track details with all feilds in JSON @app.route("/api/") def get_single_track(track_id): + global current_track_id + if track_id == 0: - with current_track_id.get_lock(): - track_id = current_track_id.value + with id_lock: + track_id = current_track_id con = sqlite3.connect(db_path) cur = con.cursor() track = cur.execute(f"SELECT * FROM critters WHERE id={track_id}").fetchone() @@ -283,14 +287,17 @@ def get_single_track(track_id): if track is not None: for (i, key) in enumerate(track_data): track_data[key] = track[i] + return Response(json.dumps(track_data | cover_path), mimetype="text/json") # Call for getting single track details with a single feild @app.route("/api/.") def get_single_field(track_id, feild): + global current_track_id + if track_id == 0: - with current_track_id.get_lock(): - track_id = current_track_id.value + with id_lock: + track_id = current_track_id result = "Unknown" if feild in db_keys: con = sqlite3.connect(db_path) -- 2.39.2