From c0e31851da3f6119f96c42a7cd521b0f6675eafa Mon Sep 17 00:00:00 2001 From: ed Date: Fri, 19 Mar 2021 21:22:56 +0100 Subject: [PATCH] add timeouts for mtp calls --- README.md | 8 ++++---- copyparty/mtag.py | 5 ++--- copyparty/up2k.py | 31 +++++++++++++++++++++++++++---- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 42b60bc1..168d4877 100644 --- a/README.md +++ b/README.md @@ -129,11 +129,11 @@ see the beautiful mess of a dictionary in [mtag.py](https://github.com/9001/copy ## file parser plugins -copyparty can invoke external programs to collect additional metadata for files using `mtp` (as argument or volume flag) +copyparty can invoke external programs to collect additional metadata for files using `mtp` (as argument or volume flag), there is a default timeout of 30sec -* `-mtp key=~/bin/audio-key.py` will execute `~/bin/audio-key.py` with filename as argument 1 to provide the `key` tag if that does not exist in the audio metadata -* `-mtp .bpm=f,~/bin/audio-bpm.py` replaces (`f,`) any existing `.bpm` tag using the `~/bin/audio-bpm.py` program -* `-v ~/music::r:cmtp=key=~/bin/audio-key.py:cmtp=.bpm=f,~/bin/audio-bpm.py` both as a per-volume config wow this is getting ugly +* `-mtp .bpm=~/bin/audio-bpm.py` will execute `~/bin/audio-bpm.py` with the audio file as argument 1 to provide the `.bpm` tag, if that does not exist in the audio metadata +* `-mtp key=f,t5,~/bin/audio-key.py` uses `~/bin/audio-key.py` to get the `key` tag, replacing any existing metadata tag (`f,`), aborting if it takes longer than 5sec (`t5,`) +* `-v ~/music::r:cmtp=.bpm=~/bin/audio-bpm.py:cmtp=key=f,t5,~/bin/audio-key.py` both as a per-volume config wow this is getting ugly # client examples diff --git a/copyparty/mtag.py b/copyparty/mtag.py index a2f15360..c3fffd21 100644 --- a/copyparty/mtag.py +++ b/copyparty/mtag.py @@ -321,12 +321,11 @@ class MTag(object): env["PYTHONPATH"] = pypath ret = {} - for tagname, binpath in parsers.items(): + for tagname, (binpath, timeout) in parsers.items(): try: - binpath = os.path.expanduser(binpath) cmd = [sys.executable, binpath, abspath] cmd = [fsenc(x) for x in cmd] - v = sp.check_output(cmd, env=env).strip() + v = sp.check_output(cmd, env=env, timeout=timeout).strip() if v: ret[tagname] = v.decode("utf-8") except: diff --git a/copyparty/up2k.py b/copyparty/up2k.py index af1a5781..567c06da 100644 --- a/copyparty/up2k.py +++ b/copyparty/up2k.py @@ -506,14 +506,37 @@ class Up2k(object): sz0 = os.path.getsize(db_path) force = {} + timeout = {} parsers = {} for parser in self.flags[ptop]["mtp"]: + orig = parser tag, parser = parser.split("=", 1) - if parser.lower().startswith("f,"): - parser = parser[2:] - force[tag] = True + while True: + try: + bp = os.path.expanduser(parser) + if os.path.exists(bp): + parsers[tag] = [bp, timeout.get(tag, 30)] + break + except: + pass - parsers[tag] = parser + try: + arg, parser = parser.split(",", 1) + arg = arg.lower() + + if arg == "f": + force[tag] = True + continue + + if arg.startswith("t"): + timeout[tag] = int(arg[1:]) + continue + + raise Exception() + + except: + self.log("invalid argument: " + orig, 1) + return q = "select count(w) from mt where k = 't:mtp'" with self.mutex: