Untested: row 328 record runner and child niceness per attempt
This commit is contained in:
1 parent
1e8e5f0865
commit
d7cef2ffbf
2 files changed
+51
-1
No files matched your search
@@ -92,3 +92,16 @@ Finally restored exact test bytes/SHA, empty git diff --stat HEAD, empty porcela
|
|||||||
no own node/Chromium remaining. Scan saw only inspection Python, which exited. Slot
|
no own node/Chromium remaining. Scan saw only inspection Python, which exited. Slot
|
||||||
returned fethry0039 while Sage rules; no test/runner modifications. Raw and normalized
|
returned fethry0039 while Sage rules; no test/runner modifications. Raw and normalized
|
||||||
receipts retained in evidence/aborted-sage4194 with provenance and explicit EXCLUDED.md.
|
receipts retained in evidence/aborted-sage4194 with provenance and explicit EXCLUDED.md.
|
||||||
|
|
||||||
|
## sage4196 priority ruling — preparation only
|
||||||
|
|
||||||
|
Sage reports active ananicy-cpp (15s checks/apply_nice); no specific Python rule proven.
|
||||||
|
Priority drift alone is no longer a stop condition and has no bearing on test validity.
|
||||||
|
Fresh CLEAR required after Della. Begin again at attempt1, initial absolute nice19, Python-B.
|
||||||
|
|
||||||
|
Only stress.py instrumentation added: a read-only100ms /proc sampler records runner and
|
||||||
|
timeout/Node descendant pid, comm, nice and elapsed sample time for every attempt, retaining
|
||||||
|
changes. Existing wait, timeout, verdict, phase order, mutation and restoration paths unchanged.
|
||||||
|
No renice loop or host/rule change. Test/manifest remain identical to36668b698. Static AST
|
||||||
|
parse only; no runner or tests executed. Stop remains fixed red, dirty tree or other unexpected
|
||||||
|
event. Final clean checks include full git status --porcelain as well as diff --stat.
|
||||||
@@ -8,6 +8,7 @@ from pathlib import Path
|
|||||||
import re
|
import re
|
||||||
import signal
|
import signal
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import threading
|
||||||
import time
|
import time
|
||||||
|
|
||||||
ROOT = Path(__file__).resolve().parents[4]
|
ROOT = Path(__file__).resolve().parents[4]
|
||||||
@@ -21,6 +22,37 @@ def digest(value):
|
|||||||
return hashlib.sha256(value).hexdigest()
|
return hashlib.sha256(value).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def sample_nice(child_pid, records, stopped):
|
||||||
|
"""Read-only samples of the runner and timeout/Node descendants (sage-4196)."""
|
||||||
|
seen = set()
|
||||||
|
started = time.monotonic()
|
||||||
|
while True:
|
||||||
|
pending = [os.getpid(), child_pid]
|
||||||
|
visited = set()
|
||||||
|
while pending:
|
||||||
|
pid = pending.pop()
|
||||||
|
if pid in visited:
|
||||||
|
continue
|
||||||
|
visited.add(pid)
|
||||||
|
proc = Path('/proc') / str(pid)
|
||||||
|
try:
|
||||||
|
stat = (proc / 'stat').read_text()
|
||||||
|
fields = stat.rsplit(')', 1)[1].split()
|
||||||
|
nice = int(fields[16]) # stat field19, after pid and parenthesized comm
|
||||||
|
command = stat.split('(', 1)[1].rsplit(')', 1)[0]
|
||||||
|
key = (pid, command, nice)
|
||||||
|
if key not in seen:
|
||||||
|
records.append({'pid': pid, 'command': command, 'nice': nice,
|
||||||
|
'seconds': round(time.monotonic() - started, 3)})
|
||||||
|
seen.add(key)
|
||||||
|
if pid != os.getpid():
|
||||||
|
pending.extend(map(int, (proc / 'task' / str(pid) / 'children').read_text().split()))
|
||||||
|
except (OSError, ValueError):
|
||||||
|
pass # Short-lived children may exit between the read-only samples.
|
||||||
|
if stopped.wait(.1):
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description=__doc__)
|
parser = argparse.ArgumentParser(description=__doc__)
|
||||||
parser.add_argument('--clear-key', required=True, help='Sage message authorizing this test slot')
|
parser.add_argument('--clear-key', required=True, help='Sage message authorizing this test slot')
|
||||||
@@ -55,6 +87,9 @@ def main():
|
|||||||
signals = []
|
signals = []
|
||||||
with log.open('w') as stream:
|
with log.open('w') as stream:
|
||||||
child = subprocess.Popen(command, cwd=ROOT, env=env, stdout=stream, stderr=subprocess.STDOUT, start_new_session=True)
|
child = subprocess.Popen(command, cwd=ROOT, env=env, stdout=stream, stderr=subprocess.STDOUT, start_new_session=True)
|
||||||
|
nice_samples, nice_stop = [], threading.Event()
|
||||||
|
sampler = threading.Thread(target=sample_nice, args=(child.pid, nice_samples, nice_stop), daemon=True)
|
||||||
|
sampler.start()
|
||||||
try:
|
try:
|
||||||
code = child.wait(timeout=135)
|
code = child.wait(timeout=135)
|
||||||
except subprocess.TimeoutExpired:
|
except subprocess.TimeoutExpired:
|
||||||
@@ -62,6 +97,8 @@ def main():
|
|||||||
signals.append('KILL')
|
signals.append('KILL')
|
||||||
code = child.wait()
|
code = child.wait()
|
||||||
finally:
|
finally:
|
||||||
|
nice_stop.set()
|
||||||
|
sampler.join()
|
||||||
try:
|
try:
|
||||||
os.killpg(child.pid, signal.SIGTERM)
|
os.killpg(child.pid, signal.SIGTERM)
|
||||||
signals.append('TERM')
|
signals.append('TERM')
|
||||||
@@ -81,7 +118,7 @@ def main():
|
|||||||
and "+ code: 'library-sync-busy'" in text and "- code: 'library-fetch-no-grant'" in text)
|
and "+ code: 'library-sync-busy'" in text and "- code: 'library-fetch-no-grant'" in text)
|
||||||
entry = {'phase': phase, 'attempt': number, 'command': command, 'TMPDIR': temporary, 'load': os.getloadavg(),
|
entry = {'phase': phase, 'attempt': number, 'command': command, 'TMPDIR': temporary, 'load': os.getloadavg(),
|
||||||
'exit': code, 'counts': counts, 'green': green, 'race': race, 'seconds': round(time.monotonic() - before, 3),
|
'exit': code, 'counts': counts, 'green': green, 'race': race, 'seconds': round(time.monotonic() - before, 3),
|
||||||
'cleanupSignals': signals, 'TAP': log.name, 'TAPSHA256': digest(log.read_bytes())}
|
'niceSamples': nice_samples, 'cleanupSignals': signals, 'TAP': log.name, 'TAPSHA256': digest(log.read_bytes())}
|
||||||
report['runs'].append(entry)
|
report['runs'].append(entry)
|
||||||
save()
|
save()
|
||||||
print(json.dumps(entry), flush=True)
|
print(json.dumps(entry), flush=True)
|
||||||
|
|||||||
Reference in new issue
Block a user