Prevent 'Too many open files' crash on store source switch
build / Linux x86_64 (push) Successful in 3m53s
build / Windows x64 (Wine) (push) Successful in 4m9s

- Raise the process soft file-descriptor limit to the hard limit at startup
  (GLib aborts the process with 'Creating pipes for GWakeup: Too many open
  files' when cover/metadata loading exhausts a 1024-soft-limit environment).
- Reduce per-loader network concurrency 8 -> 6 threads to lower socket
  pressure against the store server.
This commit is contained in:
2026-09-14 23:11:51 -04:00
parent a4d132f134
commit 99e9cdc49a
+18 -2
View File
@@ -136,7 +136,7 @@ class CoverLoader(QObject):
def run(self):
from concurrent.futures import ThreadPoolExecutor, as_completed
pool = ThreadPoolExecutor(max_workers=8)
pool = ThreadPoolExecutor(max_workers=6)
futures = {
pool.submit(load_cover, it): i
for i, it in enumerate(self.items)
@@ -1634,7 +1634,7 @@ class StoreCoverLoader(QObject):
def run(self):
from concurrent.futures import ThreadPoolExecutor, as_completed
pool = ThreadPoolExecutor(max_workers=8)
pool = ThreadPoolExecutor(max_workers=6)
futures = {
pool.submit(load_cover, it, 8, self.quick): row
for row, it in self.tasks
@@ -5954,8 +5954,24 @@ class MainWindow(QMainWindow):
event.accept()
def _raise_nofile_limit():
"""Raise the soft file-descriptor limit to the hard limit.
Cover/metadata loading opens many short-lived sockets, and each worker
QThread's GLib event dispatcher creates a wakeup pipe. On systems with a
1024 soft limit this aborts the process with GLib's "Too many open files".
"""
try:
import resource
_soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE)
resource.setrlimit(resource.RLIMIT_NOFILE, (hard, hard))
except Exception: # noqa: BLE001 - best effort, never block startup
pass
def main():
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)-7s %(name)-14s %(message)s")
_raise_nofile_limit()
init_db() # migrate legacy on-share DB/covers to local storage, then schema
# Auto-ingest any missing DATs so scanning matches against the catalog
# even on a fresh/reset database (no manual `python -m app.ingest` step).