Skip to content

linuxcncrsh: Fix race between SET JOINT_HOME and SET JOINT_WAIT_HOMED - #4351

Merged
BsAtHome merged 1 commit into
LinuxCNC:masterfrom
grandixximo:emcrsh-wait-homed
Aug 7, 2026
Merged

linuxcncrsh: Fix race between SET JOINT_HOME and SET JOINT_WAIT_HOMED#4351
BsAtHome merged 1 commit into
LinuxCNC:masterfrom
grandixximo:emcrsh-wait-homed

Conversation

@grandixximo

Copy link
Copy Markdown
Contributor

Problem

Intermittent tests/linuxcncrsh failures on slow CI runners (seen on ubuntu-24.04-arm, e.g. a recent docs-only PR).

SET JOINT_HOME is acknowledged when task has received the command, but the motion controller raises the homing flag only after its next servo-thread run, and the status needs to propagate back. A SET JOINT_WAIT_HOMED issued in that window was refused with "not homed and not in the process of homing". In the test this cascaded: homing was still in progress when the next SET JOINT_HOME arrived, which then failed with "Homing not possible until current homing process is finished", and the expected output no longer matched.

Fix

Give the motion controller a chance to catch up before declaring the error: wait for the homing flag to appear one heartbeat at a time, the same way SET MACHINE and SET ESTOP already wait for the motion controller. If homing never commences, the same error is raised as before.

Verified: tests/linuxcncrsh and tests/linuxcncrsh-tcp pass, and SET JOINT_WAIT_HOMED on a joint that was never commanded to home still NAKs with the same message.

@BsAtHome

BsAtHome commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Nice... So, the race is in the time between sending the home command and waiting for homing. Tricky one.

But, wouldn't it then be better to assert that all the joints commanded to home are actually in the homing state in setJointHome()? This may be tricky too because a homed joint will not move into the homing state afaik.

Anyway, I think it could be done after a successful call to sendHome() to see if the requested joint(s) are either already in the home state or in the homing state, using the same heartbeat trick.

Maybe we need both checks?

@grandixximo

Copy link
Copy Markdown
Contributor Author

Good point, I added both checks. setJointHome() now waits after sendHome(), one heartbeat at a time, until the requested joint is homing or homed, and NAKs with "did not start homing" if that never happens. A side effect I like: motion silently ignores the home command in several paths (not in joint mode, homing-inhibit, another homing in progress) while task still acks the echo, so those cases now produce a NAK instead of a silent no-op.

On the homed joint: in normal configs it does re-enter the homing state (HOME_START sets homing=1 and clears homed). The case where it does not is HOME_NO_REHOME (absolute encoders), which goes straight back to HOME_IDLE, so the homing || homed check covers it as you suggested.

The assert only runs for a specific joint, not for home-all (-1), because home-all legitimately skips joints without HOME_SEQUENCE and those never raise either flag. I kept the grace wait in setJointWaitHomed() too, since the homing may have been started from another UI and the same echo-to-status race applies there.

Comment thread src/emc/usr_intf/emcrsh.cc Outdated
SET JOINT_HOME is acknowledged when task has received the command, but the motion controller raises the homing flag only after its next servo-thread run and the status needs to propagate back through task. A SET JOINT_WAIT_HOMED issued in between was refused with 'not homed and not in the process of homing', and the following homing commands then failed with 'Homing not possible until current homing process is finished'. This showed up as intermittent tests/linuxcncrsh failures on slow CI runners.

SET JOINT_HOME now waits for the requested joint to become homing or homed, one heartbeat at a time, the same way SET MACHINE and SET ESTOP wait for the motion controller to catch up, and refuses the command if homing never starts. A homed joint may legitimately not enter the homing state again (HOME_NO_REHOME), hence the check for either state. Home-all (-1) is excluded because joints without HOME_SEQUENCE are skipped by design. SET JOINT_WAIT_HOMED keeps a grace wait for the homing flag before declaring the error, since the homing may have been started through a different user interface.
@BsAtHome
BsAtHome merged commit 132c2b8 into LinuxCNC:master Aug 7, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants