51 lines
2.6 KiB
JavaScript
51 lines
2.6 KiB
JavaScript
// 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);
|
|
}
|