// Test-copy observations only: bracket the supervisor's inner timer before // clean_session scans the host's /proc. Keep all shipped control flow intact. import { readProbeSeconds } from './case-p10-timing-fixture.mjs'; export { readProbeSeconds }; const BEGIN = '# row253-supervisor-begin\n'; const END = '# row253-supervisor-end\n'; const TIMER = '"$sleep_bin" "$seconds" & timer=$!\n'; const FINISH = 'finish() {\n local rc="$?"\n'; function unique(source, anchor) { const at=source.indexOf(anchor); if(at<0 || source.indexOf(anchor,at+anchor.length)>=0) throw new Error('inner observer anchor must occur exactly once'); return at; } function innerObservers(clock) { // The literal path survives env -i in the fake sudo. It is a private scratch // file, never a product input. Quote even paths containing shell metacharacters. const file="'"+clock.replaceAll("'", "'\\''")+"'"; return { begin:`# inner-observer-begin\n{ read -r timing2_up timing2_spare < /proc/uptime &&\n printf 'begin %s\\n' "$timing2_up" >> ${file}; } 2>/dev/null || :\n# inner-observer-begin-end\n`, end:` # inner-observer-end\n { read -r timing2_up timing2_spare < /proc/uptime &&\n printf 'end %s\\n' "$timing2_up" >> ${file}; } 2>/dev/null || :\n # inner-observer-end-end\n`, }; } export function instrumentInnerTimer(source,clock) { const from=unique(source,BEGIN),to=unique(source,END); if(to<=from)throw new Error('inner observer scope is reversed'); let supervisor=source.slice(from,to); unique(supervisor,TIMER);unique(supervisor,FINISH); const blocks=innerObservers(clock); supervisor=supervisor.replace(TIMER,blocks.begin+TIMER).replace(FINISH,FINISH+blocks.end); return source.slice(0,from)+supervisor+source.slice(to); } export function removeInnerObservers(source,clock) { for(const block of Object.values(innerObservers(clock))){unique(source,block);source=source.replace(block,'');} return source; } // Reuse the timing2 finish-entry stamp, moving only the other observation. // The end is in the supervisor, after clean_session and both waits, immediately // before exit. Parent scheduling and process start-up never enter this pair. export function instrumentCleanupTimer(source,clock) { const blocks=innerObservers(clock); let observed=instrumentInnerTimer(source,clock); const from=unique(observed,BEGIN),to=unique(observed,END); let supervisor=observed.slice(from,to); const exit=' exit "$rc"\n'; unique(supervisor,exit); supervisor=supervisor.replace(blocks.begin,'').replace(blocks.end,blocks.begin); supervisor=supervisor.replace(exit,blocks.end+exit); return observed.slice(0,from)+supervisor+observed.slice(to); }