mirror of
https://github.com/elwrcl/intel-hard-lab.git
synced 2026-10-31 07:48:02 +03:00
105 lines
3.4 KiB
Python
105 lines
3.4 KiB
Python
#!/usr/bin/env python3
|
|
import glob
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
import time
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
|
|
def now_iso():
|
|
return datetime.now().astimezone().isoformat(timespec="seconds")
|
|
|
|
|
|
def meminfo():
|
|
d = {}
|
|
with open("/proc/meminfo") as f:
|
|
for line in f:
|
|
k, v = line.split(":", 1)
|
|
d[k.strip()] = int(v.split()[0])
|
|
return d
|
|
|
|
|
|
def main():
|
|
outdir = Path(sys.argv[1]) if len(sys.argv) > 1 else Path.cwd() / "hangs"
|
|
poll = int(sys.argv[2]) if len(sys.argv) > 2 else 10
|
|
|
|
err = ""
|
|
for c in sorted(glob.glob("/sys/class/drm/card*/error")):
|
|
err = c
|
|
break
|
|
|
|
if not err:
|
|
print("no /sys/class/drm/card*/error — is i915 loaded?", file=sys.stderr)
|
|
elif not os.access(err, os.R_OK):
|
|
print(f"cannot read {err} — rerun with sudo for GPU hang capture", file=sys.stderr)
|
|
err = ""
|
|
|
|
outdir.mkdir(parents=True, exist_ok=True)
|
|
hangs_txt = outdir / "hangs.txt"
|
|
mem_log = outdir / "mem.log"
|
|
|
|
print(f"watching {err or '(memory only)'} every {poll}s -> {outdir}")
|
|
with open(hangs_txt, "a") as f:
|
|
f.write(f"{now_iso()} watch started\n")
|
|
|
|
n = 0
|
|
while True:
|
|
if err and os.path.getsize(err) > 0:
|
|
n += 1
|
|
stamp = datetime.now().strftime("%Y%m%d-%H%M%S")
|
|
hang_f = outdir / f"hang-{stamp}.txt"
|
|
data = open(err, "rb").read()
|
|
hang_f.write_bytes(data)
|
|
|
|
with open(hangs_txt, "a") as hf:
|
|
for line in data.decode(errors="replace").splitlines():
|
|
if line.startswith(("GPU HANG", "Kernel", "Time")):
|
|
hf.write(line + "\n")
|
|
break
|
|
msg = f"{now_iso()} hang #{n} -> {hang_f} ({hang_f.stat().st_size} B)"
|
|
hf.write(msg + "\n")
|
|
print(msg)
|
|
|
|
dmesg = subprocess.run(["dmesg"], capture_output=True, text=True).stdout
|
|
matched = [l for l in dmesg.splitlines()
|
|
if any(k.lower() in l.lower() for k in ("GPU HANG", "reset", "hangcheck"))]
|
|
(outdir / f"dmesg-{stamp}.txt").write_text("\n".join(matched[-20:]) + ("\n" if matched else ""))
|
|
|
|
with open(err, "w") as ef:
|
|
ef.write("1")
|
|
|
|
mi = meminfo()
|
|
avail = mi.get("MemAvailable", 0)
|
|
swtot = mi.get("SwapTotal", 0)
|
|
swfree = mi.get("SwapFree", 0)
|
|
sunrecl = mi.get("SUnreclaim", 0)
|
|
ptbl = mi.get("PageTables", 0)
|
|
|
|
ps = subprocess.run(["ps", "-eo", "rss,comm", "--sort=-rss", "--no-headers"],
|
|
capture_output=True, text=True).stdout
|
|
top3 = []
|
|
for line in ps.splitlines()[:3]:
|
|
parts = line.split(None, 1)
|
|
if len(parts) == 2:
|
|
rss, comm = parts
|
|
top3.append(f"{comm}:{int(rss) // 1024}M")
|
|
top3_str = " ".join(top3) + (" " if top3 else "")
|
|
|
|
line = (f"{now_iso()} avail={avail // 1024}M swapused={(swtot - swfree) // 1024}M "
|
|
f"sunreclaim={sunrecl // 1024}M pagetables={ptbl // 1024}M {top3_str}\n")
|
|
with open(mem_log, "a") as mf:
|
|
mf.write(line)
|
|
try:
|
|
subprocess.run(["sync", "-d", str(mem_log)], check=True,
|
|
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
except subprocess.CalledProcessError:
|
|
subprocess.run(["sync"])
|
|
|
|
time.sleep(poll)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|