diff --git a/copyparty/mtag.py b/copyparty/mtag.py index 82ff63b6..d9971343 100644 --- a/copyparty/mtag.py +++ b/copyparty/mtag.py @@ -118,7 +118,7 @@ def ffprobe( b"--", fsenc(abspath), ] - rc, so, se = runcmd(cmd, timeout=timeout) + rc, so, se = runcmd(cmd, timeout=timeout, nice=True) retchk(rc, cmd, se) return parse_ffprobe(so) @@ -562,6 +562,7 @@ class MTag(object): args = { "env": env, + "nice": True, "timeout": parser.timeout, "kill": parser.kill, "capture": parser.capture, @@ -572,11 +573,6 @@ class MTag(object): zd.update(ret) args["sin"] = json.dumps(zd).encode("utf-8", "replace") - if WINDOWS: - args["creationflags"] = 0x4000 - else: - cmd = ["nice"] + cmd - bcmd = [sfsenc(x) for x in cmd[:-1]] + [fsenc(cmd[-1])] rc, v, err = runcmd(bcmd, **args) # type: ignore retchk(rc, bcmd, err, self.log, 5, self.args.mtag_v) diff --git a/copyparty/th_srv.py b/copyparty/th_srv.py index e4398887..233de259 100644 --- a/copyparty/th_srv.py +++ b/copyparty/th_srv.py @@ -468,7 +468,7 @@ class ThumbSrv(object): def _run_ff(self, cmd: list[bytes], vn: VFS) -> None: # self.log((b" ".join(cmd)).decode("utf-8")) - ret, _, serr = runcmd(cmd, timeout=vn.flags["convt"]) + ret, _, serr = runcmd(cmd, timeout=vn.flags["convt"], nice=True) if not ret: return diff --git a/copyparty/util.py b/copyparty/util.py index 297972a2..95388714 100644 --- a/copyparty/util.py +++ b/copyparty/util.py @@ -2508,9 +2508,34 @@ def killtree(root: int) -> None: pass +def _find_nice() -> str: + if WINDOWS: + return "" # use creationflags + + try: + zs = shutil.which("nice") + if zs: + return zs + except: + pass + + # busted PATHs and/or py2 + for zs in ("/bin", "/sbin", "/usr/bin", "/usr/sbin"): + zs += "/nice" + if os.path.exists(zs): + return zs + + return "" + + +NICES = _find_nice() +NICEB = NICES.encode("utf-8") + + def runcmd( argv: Union[list[bytes], list[str]], timeout: Optional[float] = None, **ka: Any ) -> tuple[int, str, str]: + isbytes = isinstance(argv[0], (bytes, bytearray)) kill = ka.pop("kill", "t") # [t]ree [m]ain [n]one capture = ka.pop("capture", 3) # 0=none 1=stdout 2=stderr 3=both @@ -2524,13 +2549,22 @@ def runcmd( berr: bytes if ANYWIN: - if isinstance(argv[0], (bytes, bytearray)): + if isbytes: if argv[0] in CMD_EXEB: argv[0] += b".exe" else: if argv[0] in CMD_EXES: argv[0] += ".exe" + if ka.pop("nice", None): + if WINDOWS: + ka["creationflags"] = 0x4000 + elif NICEB: + if isbytes: + argv = [NICEB] + argv + else: + argv = [NICES] + argv + p = sp.Popen(argv, stdout=cout, stderr=cerr, **ka) if not timeout or PY2: bout, berr = p.communicate(sin) @@ -2678,6 +2712,7 @@ def _parsehook( sp_ka = { "env": env, + "nice": True, "timeout": tout, "kill": kill, "capture": cap,