Commits the 5 product paths and 7 gate helpers of the row 227 R4 source overlay on top of HEAD 5a0c801cb. scripts/case2/console.mjs is already committed at HEAD and is not part of this commit. The R4 independent review is sha256 6667baaa6af9d6d78a3ec7c64d9f3163ecbc350b94050f62899d9c01deabe002, verdict APPROVE source-only. Packet hashes: PACKET.sha256 4eb60915b2144137df9b5a42afd0c5b266718d71de051fb8be53a27430a2cad4, CURRENT-SOURCE.sha256 0cfd47c2073bc18a3ba7bff1ce6fdf39fe33a64b7fca209be71517b9feb89020. The 12 committed files match the review hash table, the applied overlay JSON (size, mode, hash) and the saved overlay tar. No scripts/test-case2.sh run exists on these bytes.
74 lines
3.4 KiB
Python
74 lines
3.4 KiB
Python
# No global PID census. JSON can neither create ownership nor select signals.
|
|
import os,time
|
|
from pathlib import Path
|
|
class Owned:
|
|
def __init__(self,boot,evidence):self.boot=boot;self.e=evidence;self.rows={};self.parents={};self.history={};self.first={}
|
|
def identity(self,pid):
|
|
try:
|
|
text=Path(f'/proc/{pid}/stat').read_text();v=text[text.rfind(')')+2:].split()
|
|
return dict(pid=pid,start=v[19],ppid=int(v[1]),state=v[0],boot=self.boot)
|
|
except FileNotFoundError:return None
|
|
def valid(self,key):
|
|
row=self.identity(key[0]);return row if row and row['start']==key[1] else None
|
|
def root(self,pid,parent):
|
|
row=self.identity(pid)
|
|
if not row or row['ppid']!=parent:raise RuntimeError('root-identity-refused')
|
|
key=(pid,row['start']);self.rows[key]=row;self.parents[key]=None;return key
|
|
def observe(self,key):
|
|
before=self.valid(key)
|
|
if not before:return None
|
|
# Only already owned PID/start may be inspected here.
|
|
directory=Path(f'/proc/{key[0]}');nice=os.getpriority(os.PRIO_PROCESS,key[0]);argv=(directory/'cmdline').read_bytes().split(b'\0')
|
|
argv=[s.decode(errors='strict') for s in argv if s];exe=os.readlink(directory/'exe') if before['state']!='Z' else ''
|
|
status=(directory/'status').read_text();cwd=os.readlink(directory/'cwd') if before['state']!='Z' else '';after=self.valid(key)
|
|
if not after:return None
|
|
ns=next((list(map(int,line.split()[1:])) for line in status.splitlines() if line.startswith('NSpid:')),[])
|
|
row=dict(**after,nice=nice,argv=argv,exe=exe,nspid=ns,cwd=cwd)
|
|
self.history[key]=row;self.first.setdefault(key,time.monotonic())
|
|
if row['state']!='Z' and nice!=19:self.e.fail('owned-native-priority-drift')
|
|
return row
|
|
def traverse(self):
|
|
# Drain newly discovered generations in this pass, with bounded work. More passes follow
|
|
# inside the same existing5s attribution window, never an extended acceptance deadline.
|
|
fresh={}
|
|
for depth in range(32):
|
|
added=False
|
|
for key in list(self.rows):
|
|
try:row=self.observe(key)
|
|
except (FileNotFoundError,ProcessLookupError):continue
|
|
if not row:continue
|
|
fresh[key]=row
|
|
if row['state']=='Z':continue
|
|
candidates=set()
|
|
try:
|
|
for task in Path(f'/proc/{key[0]}/task').iterdir():
|
|
try:candidates.update(int(v) for v in (task/'children').read_text().split())
|
|
except FileNotFoundError:pass
|
|
except FileNotFoundError:continue
|
|
if not self.valid(key):continue
|
|
for pid in candidates:
|
|
child=self.identity(pid)
|
|
if child and child['ppid']==key[0] and self.valid(key):
|
|
ck=(pid,child['start'])
|
|
if ck not in self.rows:self.rows[ck]=child;self.parents[ck]=key;added=True
|
|
if not added:break
|
|
return fresh
|
|
def descends(self,key,parent,fresh):
|
|
walked=set()
|
|
while key in fresh and key not in walked:
|
|
if key==parent:return True
|
|
walked.add(key);pk=self.parents.get(key);current=self.valid(key)
|
|
if pk is None or pk not in fresh or not current or current['ppid']!=pk[0] or not self.valid(pk):return False
|
|
key=pk
|
|
return False
|
|
def selected_env(self,key):
|
|
if not self.valid(key):return None
|
|
# Never dump provider credentials or the whole environment.
|
|
raw=Path(f'/proc/{key[0]}/environ').read_bytes();out={}
|
|
for value in raw.split(b'\0'):
|
|
name,sep,val=value.partition(b'=')
|
|
if name in [b'NODE_OPTIONS',b'MOSAIC_TURN_MARKER']:out[name.decode()]=val.decode()
|
|
return out if self.valid(key) else None
|
|
def fresh_survivors(self):
|
|
return [row for key in list(self.rows) if (row:=self.observe(key)) and row['state']!='Z']
|