feat(vm): debug a program on more than one worker #726
No reviewers
Labels
No labels
loop
queue/failed
queue/queued
ready
status/parked
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
torbscript/language!726
Loading…
Reference in a new issue
No description provided.
Delete branch "loop/719-debug-workers-vm"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #719
Refs #41
Task: torbscript/language#719 (implementation, VM half; the runtime half is merged in #722).
What
A debugged program keeps one worker unless it asks for a pool (
tasks { workers }in the manifest, orTORB_WORKERS). Then:workersForgives every worker an interpreter with aDebugThreadof its own (number1 and up) and the debugger.reachStatementparks first if another thread holds, counts down and polls the breakpoints under the hold, and only when it means to stop holds again, decides again (confirmed) and stops.reachPanicbrackets the panic announcement with hold/release.DebugThread(framesIn); frame ids are laid out by thread, so a frame has the same id whether its task is parked on a worker or waits in its block.Debugger.stepOwner); a breakpoint another worker hits while the first stands stays pending and stops aftercontinue, with its ownthreadId.tests/debug/workers.dap(+workers/main.trb,workers/project.trbwithtasks { workers = 2 },workers.expected). It stops only where a channel orders it: follower line 8, leader line 24, follower line 11. No existing session file was touched.docs/tooling/torb-debug.mdand the regeneratedskills/page.Test and honesty notes
torbbinaries fail on GLIBC_2.38 except the nightly, which only doescheck/format). With the nightly:torb checkandtorb format --checkare clean on the changed compiler files and on the new session program;docs skill docs skillswas run and--checkis clean.workers.expectedwas written by hand from the design of the session and has not been produced by a run. If CI shows a difference, the first push is expected to need a correction of the expected file (frame ids, whether stdlib channel operations show up as threads); I check each difference for meaning before changing it.sh tools/debug.sh --filter workers) was not run locally. It cannot be claimed.47b6d189): the breakpoint at line 10 is gone, the one that raced the leader's breakpoint at line 24 for the first stop after the wake. Every remaining stop is ordered by a channel: the leader cannot reach line 24 before the follower's offer, and the follower cannot reach line 11 before the leader's answer. At stop 2 the follower's frame reads line 10 whether it is held before thenext()or waits in it, andthreadsis no longer asked there (it would list the follower'snext()only in one of the two cases).reachParallel,stepOwner) has the review of this PR and no session assertion. Also open: the 50-run check of #719 (workers.expectedbyte-identical over 50 runs) was not run; it needs a CI-builttorb.torb debugas the pool is assumed fromprepared.pool; if CI shows one worker, the fallback is a.workersfile intools/debug.sh.A debugged program keeps one worker unless it asks for a pool (`tasks { workers }` or `TORB_WORKERS`). Then every worker has an interpreter with a thread record of its own and the debugger's hooks: a statement parks while another thread holds, counts and polls under the hold, and holds and decides again before it stops. The frames of a task parked on another worker are read from that worker, a step belongs to the thread that began it, and a breakpoint hit by a second worker while the first stands is kept for the next `continue`. tests/debug/workers.dap drives two tasks on two workers, ordered by channels. Closes #719 Refs #41Review of
ec5457d6(CI green on this head: tier A includingtests/debug against .expected, bootstrap, gates, pdisc).Checklist
tests/debug/workersexists and passed once in tier A on this head. See finding 1.reachParallel,stopReasonOf,stepOwner, frames of a parked thread,originaddress for locals, snippet refusal on a worker). A debugged run with one worker keeps the old path.docs/tooling/torb-debug.mdand the regeneratedskills/page are updated; pdisc green.Findings
workers.expectedis byte-identical across 50 consecutive runs ofsh tools/debug.sh --filter workers". It was not run (the PR body says so), and the PR body also names a known race in the session: after the follower'sadd()wakes the leader, stop 2 (follower, breakpoint 2 at line 10) versus the leader's breakpoint 3 (line 24) depends on which worker reaches its next statement first. One green tier A run does not show this holds.workers.expectedwas also hand-written and has already needed one correction. This session runs in tier A on every PR of the repo, so a flip becomes a red gate on unrelated PRs. Please either remove the race from the session or show the 50-run result.workers.dap, so the only stop after the wake is the leader's (line 24). The follower is then either held before or waiting in line 10'snext(), which is the same frame line in both cases, and the stop order no longer depends on timing. If criterion 6 ("a breakpoint hit by a second worker while the first is stopped") needs the current shape, say which assertion needs it and why it cannot be forced by a channel.torb(for example a one-off job or a loop step on this branch) and post the count in the PR.Non-blocking
tools/debug-cost.shnumbers are not read; the non-parallel path only gains anif debugger.parallelbranch, so I do not expect movement.Addressed finding 1 in
47b6d189by removing the race, as suggested: breakpoint line 10 dropped fromworkers.dap,workers.expectedadjusted (breakpoint ids 1/2/3, the leader's stop now follows the firstcontinuedirectly,threadsno longer asked at stop 2). Everything else in the session is unchanged.workers.expectedis again hand-edited, not produced by a run; CI tier A on this head is the first run, and a difference gets checked for meaning before the file changes. Criterion 6 of #719 (pending breakpoint of a second worker) cannot be ordered by a channel and is not asserted by the session; the PR body says so, as it does for the 50-run check. Standing approval (docs/standing-approval.md in orion/infra) is the sign-off for this PR.Not mergeable on
47b6d18: conflict, rebase and resolve.Main has moved (
cbf0e2c) and touches files this PR also changes:docs/design/DEBUGGER.md,docs/tooling/torb-debug.mdandskills/torbscript/references/tooling/torb-debug.md. After the rebase, regenerate theskills/page rather than merging it by hand.My earlier blocker (the racy breakpoint in the workers session) is resolved in
47b6d18and CI is green on this head (tier A and B, gates, pdisc). On the rebase I will check only the conflict resolution and the range-diff.47b6d189b67b0e7593f9Rebased onto main (
cbf0e2c0), head7b0e7593; no code change. One conflict, indocs/design/DEBUGGER.mdsection 20: kept main's current wording of the native-programs bullet and this PR's worker-pool bullet.docs/tooling/torb-debug.mdmerged cleanly; theskills/page differs from the docs page only in the same link rewrites as on main (diff is the same 17 lines as on main), so it equals whattorb docs skillproduces.git range-diffof the three commits shows only the section 20 resolution. CI runs fresh on this head.Review of
7b0e7593(re-review after the rebase ontocbf0e2c0). Combined status success: tier A (includingtests/debug against .expected), bootstrap, gates, pdisc; tier B skipped.Checklist
workers.expectedmatchesworkers.dap(breakpoint ids 1/2/3) and tier A passed on this head.skills/page equals the docs page change. Branch is mergeable.tests/debug/workerspresent, no existing session file touched.docs/tooling/torb-debug.mdand theskills/page updated; pdisc green.Non-blocking
reachParallel/stepOwner). A follow-up issue for a pending-breakpoint test (for example a unit-level one, since no channel can order it in a session) would close the second.