Merge pull request #357 from arabcoders/dev
Some checks failed
Build WebView wrappers / build (amd64, ubuntu-latest) (push) Has been cancelled
Build WebView wrappers / build (amd64, windows-latest) (push) Has been cancelled
Build WebView wrappers / build (arm64, macos-latest) (push) Has been cancelled
Build WebView wrappers / build (arm64, ubuntu-latest) (push) Has been cancelled
Build WebView wrappers / build (arm64, windows-latest) (push) Has been cancelled
Some checks failed
Build WebView wrappers / build (amd64, ubuntu-latest) (push) Has been cancelled
Build WebView wrappers / build (amd64, windows-latest) (push) Has been cancelled
Build WebView wrappers / build (arm64, macos-latest) (push) Has been cancelled
Build WebView wrappers / build (arm64, ubuntu-latest) (push) Has been cancelled
Build WebView wrappers / build (arm64, windows-latest) (push) Has been cancelled
Fix threading issue on windows exe
This commit is contained in:
commit
517d4e7528
4 changed files with 58 additions and 2 deletions
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
|
|
@ -98,6 +98,7 @@
|
||||||
"tmpfilename",
|
"tmpfilename",
|
||||||
"ungroup",
|
"ungroup",
|
||||||
"unnegated",
|
"unnegated",
|
||||||
|
"unpickleable",
|
||||||
"Unraid",
|
"Unraid",
|
||||||
"upgrader",
|
"upgrader",
|
||||||
"urandom",
|
"urandom",
|
||||||
|
|
|
||||||
|
|
@ -167,6 +167,9 @@ class Download:
|
||||||
self.status_queue.put({"id": self.id, "filename": filename})
|
self.status_queue.put({"id": self.id, "filename": filename})
|
||||||
|
|
||||||
def _download(self):
|
def _download(self):
|
||||||
|
if not self._notify:
|
||||||
|
self._notify = EventBus.get_instance()
|
||||||
|
|
||||||
cookie_file = None
|
cookie_file = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -360,6 +363,13 @@ class Download:
|
||||||
self.cancel_in_progress = True
|
self.cancel_in_progress = True
|
||||||
procId: int | None = self.proc.ident
|
procId: int | None = self.proc.ident
|
||||||
|
|
||||||
|
if not procId:
|
||||||
|
if self.proc:
|
||||||
|
self.proc.close()
|
||||||
|
self.proc = None
|
||||||
|
self.logger.warning("Attempted to close download process, but it is not running.")
|
||||||
|
return False
|
||||||
|
|
||||||
self.logger.info(f"Closing PID='{procId}' download process.")
|
self.logger.info(f"Closing PID='{procId}' download process.")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -570,3 +580,14 @@ class Download:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def __getstate__(self):
|
||||||
|
state = self.__dict__.copy()
|
||||||
|
|
||||||
|
# Exclude (unpickleable) keys during pickling, this issue arise mostly on Windows.
|
||||||
|
excluded_keys = ("_notify",)
|
||||||
|
for key in excluded_keys:
|
||||||
|
if key in state:
|
||||||
|
state[key] = None
|
||||||
|
|
||||||
|
return state
|
||||||
|
|
|
||||||
|
|
@ -1115,9 +1115,12 @@ class DownloadQueue(metaclass=Singleton):
|
||||||
LOG.exception(e)
|
LOG.exception(e)
|
||||||
LOG.error(f"Failed to retry item '{item_ref}'. {e!s}")
|
LOG.error(f"Failed to retry item '{item_ref}'. {e!s}")
|
||||||
|
|
||||||
def _handle_task_exception(self, task: asyncio.Task):
|
def _handle_task_exception(self, task: asyncio.Task) -> None:
|
||||||
if task.cancelled():
|
if task.cancelled():
|
||||||
return
|
return
|
||||||
|
|
||||||
if exc := task.exception():
|
if exc := task.exception():
|
||||||
LOG.error(f"Unhandled exception in background task: {exc!s}")
|
import traceback
|
||||||
|
|
||||||
|
task_name: str = task.get_name() if task.get_name() else "unknown_task"
|
||||||
|
LOG.error(f"Unhandled exception in background task '{task_name}': {exc!s}. {traceback.format_exc()}")
|
||||||
|
|
|
||||||
|
|
@ -1377,3 +1377,34 @@ def ytdlp_reject(entry: dict, yt_params: dict) -> tuple[bool, str]:
|
||||||
return (False, f'Video "{entry.get("title", "unknown")}" is age restricted.')
|
return (False, f'Video "{entry.get("title", "unknown")}" is age restricted.')
|
||||||
|
|
||||||
return (True, "")
|
return (True, "")
|
||||||
|
|
||||||
|
|
||||||
|
def find_unpickleable(obj, name="root", seen=None):
|
||||||
|
import pickle
|
||||||
|
|
||||||
|
if seen is None:
|
||||||
|
seen = set()
|
||||||
|
|
||||||
|
if id(obj) in seen:
|
||||||
|
return
|
||||||
|
|
||||||
|
seen.add(id(obj))
|
||||||
|
|
||||||
|
try:
|
||||||
|
pickle.dumps(obj)
|
||||||
|
except Exception as e:
|
||||||
|
LOG.error(f"[UNPICKLEABLE] {name}: {e}")
|
||||||
|
|
||||||
|
if isinstance(obj, dict):
|
||||||
|
for k, v in obj.items():
|
||||||
|
find_unpickleable(v, f"{name}[{repr(k)!s}]", seen)
|
||||||
|
elif hasattr(obj, "__dict__"):
|
||||||
|
for attr in vars(obj):
|
||||||
|
try:
|
||||||
|
value = getattr(obj, attr)
|
||||||
|
find_unpickleable(value, f"{name}.{attr}", seen)
|
||||||
|
except Exception as ie:
|
||||||
|
LOG.error(f"[ERROR] Accessing {name}.{attr}: {ie}")
|
||||||
|
elif isinstance(obj, (list, tuple, set)):
|
||||||
|
for idx, item in enumerate(obj):
|
||||||
|
find_unpickleable(item, f"{name}[{idx}]", seen)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue