forgetest: motion tests end on the machine's idle; the Grbl client survives a soft reset

wait_idle returned on a stale Idle before a just-commanded move began,
and the tests declared PASS on grblHAL's Idle while the kernel still
played the stream depth and the decel tail (the baseline caught
state=running after motion.pacing). Every motion test now ends on
forgectrl's idle (machine_idle), and wait_idle ignores an Idle inside a
short grace unless a non-Idle state was seen.

status_report re-sends '?' every 0.5 s until a report arrives: a soft
reset (^X) flushes the controller's read buffer and eats a '?' that lands
in it - the bench saw motion.cancel-abort error with no report for 5 s
after the abort while the controller answered the next '?' at once.

motion.deadman: the SIGSTOP drill waited for a running controller and
got the killed pid back before the supervisor reaped it (drill 1 already
waited for a different pid); and the forgectrl-restart drill expected the
busy controller's pid to survive the retake, but a retake under the
broker is stop-at-idle, re-probe, start a supervised controller (the old
inherited fd cannot be adopted) - the check is now: the move finished
unmanaged, supervision came back running and verified. Bench-proven
2026-08-16: kill respawn 1.3 s, hang -> underrun 0.21 s, retake at idle.
This commit is contained in:
ScottW514
2026-08-16 14:21:53 -04:00
parent 0312dec22b
commit d4e2f85538
2 changed files with 43 additions and 12 deletions
+8 -1
View File
@@ -276,10 +276,14 @@ class Grbl:
self.send_raw(bytes([byte]))
def status_report(self):
"""One '?' report, parsed: {'state': 'Idle', 'MPos': (x,y,z), ...}."""
"""One '?' report, parsed: {'state': 'Idle', 'MPos': (x,y,z), ...}.
The '?' is re-sent every 0.5 s until a report arrives: a soft
reset (^X) flushes the controller's read buffer and eats a '?'
that lands in it."""
self.drain()
self.send_raw(b"?")
deadline = time.time() + self.timeout
resend = time.time() + 0.5
self.sock.settimeout(0.2)
while time.time() < deadline:
try:
@@ -288,6 +292,9 @@ class Grbl:
self.buf += d
except socket.timeout:
pass
if time.time() >= resend:
self.send_raw(b"?")
resend = time.time() + 0.5
i = self.buf.find(b"<")
j = self.buf.find(b">", i + 1) if i >= 0 else -1
if i >= 0 and j > i: