diff --git a/harbor/reverse.py b/harbor/reverse.py index 3cbacbe..a5a7de5 100644 --- a/harbor/reverse.py +++ b/harbor/reverse.py @@ -648,6 +648,30 @@ def behaviour_check(config, targets, decomp=None, precision=24): return [{k: r[k] for k in keep if k in r} for r in rows] +def pid_alive(pid): + """True while process `pid` runs (Windows: OpenProcess and GetExitCodeProcess; never signals it).""" + try: + pid = int(pid) + except (TypeError, ValueError): + return False + if os.name != "nt": + try: + os.kill(pid, 0) + return True + except OSError: + return False + import ctypes + kernel = ctypes.windll.kernel32 + handle = kernel.OpenProcess(0x1000, False, pid) # PROCESS_QUERY_LIMITED_INFORMATION + if not handle: + return False + try: + code = ctypes.c_ulong() + return bool(kernel.GetExitCodeProcess(handle, ctypes.byref(code))) and code.value == 259 # STILL_ACTIVE + finally: + kernel.CloseHandle(handle) + + class _exclusive: """A lock file shared between processes: wait for it, hold it, remove it (stale after two hours).""" @@ -665,7 +689,9 @@ class _exclusive: return self except FileExistsError: try: - if time.time() - self.path.stat().st_mtime > 7200: + holder = self.path.read_text(encoding="utf-8").strip() + age = time.time() - self.path.stat().st_mtime + if (holder and not pid_alive(holder)) or (not holder and age > 5) or age > 7200: self.path.unlink() continue except FileNotFoundError: