Skip to content

emcmodule: retry the tool mmap attach in stat.poll() - #4658

Merged
grandixximo merged 1 commit into
LinuxCNC:masterfrom
grandixximo:tool-mmap-poll-retry
Oct 11, 2026
Merged

grandixximo merged 1 commit into
LinuxCNC:masterfrom
grandixximo:tool-mmap-poll-retry

Conversation

@grandixximo

Copy link
Copy Markdown
Contributor

Fixes #4656.

The first stat.poll() in a process tried tool_mmap_user() once; if task had not created ~/.tool.mmap yet, a static flag latched and every later poll() returned NULL without an exception (SystemError forever). ui-smoke polls before task is up, so isolated runs (#4648) failed with task not ready within 60.0s.

  • poll() retries the attach until it succeeds; initialized stays 0 meanwhile, so tool_table/toolinfo report no data. Correction to my issue comment: a NULL base is not safe in tooldata_get() (it exits), which is why the gate stays.
  • tool_mmap_user() warns once and treats a file shorter than the mapping as absent (creator truncates before extending; mapping it then would SIGBUS).
  • drive.py: drop the comment calling the SystemError normal.

Tested in a sandbox with a fresh HOME and no ~/.tool.mmap: ui-smoke axis fails on master with the issue's error and passes with this; tests/ui-smoke plus tests/*tool* 20/20. With this, the touch $HOME/.tool.mmap in #4648 should not be needed.

Comment thread src/emc/tooldata/tooldata_mmap.cc
@BsAtHome

BsAtHome commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

The real problem is that the progression is an effective race.

@grandixximo

Copy link
Copy Markdown
Contributor Author

Agreed. The launcher is racy: loadusr -Wn inihal returns at the hal_ready() in ini_hal_init(), before motion and interp init and before Task::Task() calls tool_mmap_creator(). halui starts in that window and calls tool_mmap_user() exactly once, so it can lose and keep a NULL base. hal_ready() cannot move later because task's motion init waits for the HAL files that load after it. I can create the file in task before ini_hal_init() so everything the launcher starts finds it; the retry in poll() stays for clients started outside the launcher (ui-smoke's drive.py, user scripts). Do you want that in this PR or as a follow-up?

Comment thread src/emc/tooldata/tooldata_mmap.cc Outdated
Comment on lines +204 to +205
snprintf(why, sizeof(why), "size %jd < %zu",
(intmax_t)st.st_size, (size_t)(TOOL_MMAP_SIZE));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be safe to cast to size_t since most syscalls use that for file size (and ssize_t if errors are to be returned). Then you don't need intmax_t as it is unclear what size int actually is. However, off_t must encapsulate at least ssize_t or the syscall would no longer be 64-bit safe.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, compared and printed as size_t; the intmax_t and <stdint.h> are gone.

@hdiethelm

Copy link
Copy Markdown
Contributor

Thanks a lot for fixing this!

It was also the reason the other tests failed, probably due to the zero size .tool.mmap in my work around, but there was no understandable error message in this case.

I cherry-picked the commits in my branch, dropped the workaround and it works nicely. Except some other bugs from my PR... ;-)

Just one thing:

tool_mmap_user(): tool mmap not available: /home/hannes/.tool.mmap: open: No such file or directory
poll(): tool mmap not available yet, retrying

I would expect a 3. message:
poll(): tool mmap available now
so it is clear that all is fine. Otherwise, it looks like an error.

I had a hard time discriminating between errors and warnings in the CI logs. And it also took me some time to discover that tool_mmap_user(): tool mmap not available was the reason the test failed.

@grandixximo

Copy link
Copy Markdown
Contributor Author

Thanks for testing it. Added: after the first warning, poll() now prints poll(): tool mmap available now once the attach succeeds.

The first stat.poll() in a process tried tool_mmap_user() once. If task
had not created ~/.tool.mmap yet, a static flag latched and every later
poll() returned NULL without setting an exception, so Python raised
SystemError forever and a new linuxcnc.stat() did not help. A stale
~/.tool.mmap from an earlier run hid it; isolated test runs and a fresh
HOME failed every time.

Retry the attach on each poll until it succeeds and leave initialized at
0 meanwhile, so tool_table and toolinfo report no data instead of
touching a NULL mapping. poll() warns once, and says when the mmap
became available, so the warning does not read as a failure (hdiethelm
asked for that after hunting the cause in CI logs).

tool_mmap_user() warns once and names the file and the step that
failed: open or fstat with the errno, or a file still shorter than the
mapping. The creator truncates before extending, and mapping the file in
that window would SIGBUS on first access, so a short file counts as
absent. BsAtHome asked for the reason and the size_t comparison.

Drop the drive.py comment that described the SystemError as normal
startup noise.

Fixes LinuxCNC#4656
@grandixximo
grandixximo force-pushed the tool-mmap-poll-retry branch from c88ed53 to 83b5368 Compare October 9, 2026 22:28
@grandixximo

Copy link
Copy Markdown
Contributor Author

Correction to my earlier reply: I misread the startup order. task's main() runs emcTaskOnce(), whose Task::Task() calls tool_mmap_creator(), before emctask_startup() reaches ini_hal_init() and its hal_ready(). So loadusr -Wn inihal only returns after the file exists, and halui and the GUI started by the launcher always find it. The race only affects clients started outside the launcher, like ui-smoke's drive.py or user scripts, and the retry in poll() covers those. No follow-up needed.

@grandixximo
grandixximo merged commit a7e0a63 into LinuxCNC:master Oct 11, 2026
17 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.

ui-smoke tests fails if $HOME/.tool.mmap does not exist

3 participants