Repository navigation
ui-smoke tests fails if $HOME/.tool.mmap does not exist #4656
Description
Activity
This is a problem in the tooldata stuff in emc/tooldata/tooldata_mmap.cc. The mmap is apparently not created and when the GUI tries to attach as a client to a non existing mmap the test fails. That means that the tool_mmap_creator() probably fails in emc/task/taskclass.cc.
When you change permissions locally to 0400, then you get in tests/ui-smoke/qtdragon/linuxcnc.err:
Note: realtime scheduling unavailable (sched_setscheduler SCHED_FIFO: Operation not permitted). Process capabilities: cap_sys_nice=no cap_ipc_lock=no. Falling back to POSIX non-realtime. Fix: 'sudo make setcap' (preferred) or 'sudo make setuid' on rtapi_app. Override (testing only): set LINUXCNC_FORCE_REALTIME=1. Note: Using POSIX non-realtime tool_mmap_creator(): file open fail: Permission denied <commandline>:0: waitpid failed milltask inihal <commandline>:0: milltask exited without becoming ready tool_mmap_user(): tool mmap not available [HAL bridge.COMMON.INIINFO][�[33mWARNING�[0m] Path not valid in INI File [RS274NGC] SUBROUTINE_PATH section: ../../../../nc_files/probe/basic_probe/macros (iniinfo.py:89) [HAL bridge.COMMON.INIINFO][�[33mWARNING�[0m] Path not valid in INI File [RS274NGC] SUBROUTINE_PATH section: /myhome/linuxcnc/nc_files/examples/ngcgui_lib (iniinfo.py:89) [HAL bridge.COMMON.INIINFO][�[33mWARNING�[0m] Path not valid in INI File [RS274NGC] SUBROUTINE_PATH section: /myhome/linuxcnc/nc_files/examples/ngcgui_lib/utilitysubs (iniinfo.py:89) No isolated CPU's found, expect some latency or set RTAPI_CPU_NUMBER to select CPU /myhome/linuxcnc.git/lib/hallib/core_sim.hal:46: Pin 'iocontrol.0.user-enable-out' does not exist Terminated exit 1 rtapi_app: exit received while not runningIt is also problematic that the mmap backing file is never cleaned up when things seem to run normally.
The error is in:
linuxcnc/src/emc/tooldata/tooldata_mmap.cc
Lines 151 to 156 in 8f05c9d
creator_fd = open(tool_mmap_fname(), TOOL_MMAP_CREATOR_OPEN_FLAGS,TOOL_MMAP_MODE); if (creator_fd < 0) { perror("tool_mmap_creator(): file open fail"); exit(EXIT_FAILURE); } When the file creation fails, then the process exits, which kills task.
The most likely problem are the flags to the open:
#define TOOL_MMAP_CREATOR_OPEN_FLAGS O_RDWR | O_CREAT | O_TRUNC | O_NOFOLLOW
The specification of
O_NOFOLLOWcan be problematic as CI most likely redirects things bit.Sorry to not hint directly to this file. There are two functions:
tool_mmap_user()which opens the file and expect it exists andtool_mmap_creator()which creates it. Looks like onlytool_mmap_user()is called in certain cases, which then fails. It's not only a CI issue, it happens also locally with the commands in the description.You won't even reach the
tool_mmap_user()if thetool_mmap_creator()fails to create the file. It simply executes anexit()and then all things fall apart.BTW, you can try to change the filename in
tool_mmap_fname()and do:static char* tool_mmap_fname(void) { if (*filename) {return filename;} snprintf(filename, sizeof(filename), "/tmp/linuxcnc-tooldata%s, TOOL_MMAP_FILENAME); return(filename); }
That would put the file in
/tmp, which should be accessible without requiring following symlinks.In CI, I got the error
tool_mmap_user(): tool mmap not availablewhich is fromtool_mmap_user(), so I thinktool_mmap_creator()is not even called.
Quick and dirty workaround: 454a737
Now it fails somewhere else, probably unrelated to this issue.Can you check something for me then...
In
tool_mmap_user()you hit thefprintf()and that means we don't see theerrno. Changefprintf(stderr,intoperror(and we should be see why it fails.Yes:
diff --git a/src/emc/tooldata/tooldata_mmap.cc b/src/emc/tooldata/tooldata_mmap.cc index 7ba07b48f7..ea9629609f 100644 --- a/src/emc/tooldata/tooldata_mmap.cc +++ b/src/emc/tooldata/tooldata_mmap.cc @@ -143,6 +143,7 @@ int tool_mmap_creator(EMC_TOOL_STAT const * ptr,int random_toolchanger) { static int inited=0; + fprintf(stderr,"tool_mmap_creator()------------------------\n"); if (inited) { fprintf(stderr,"Error: tool_mmap_creator already called BYE\n"); exit(EXIT_FAILURE); @@ -188,6 +189,7 @@ int tool_mmap_user() int fd = open(tool_mmap_fname(), TOOL_MMAP_USER_OPEN_FLAGS, TOOL_MMAP_MODE); + fprintf(stderr,"tool_mmap_user()------------------------\n"); if (fd < 0) { /* ** For the LinuxCNC application, tool_mmap_creator() @@ -197,7 +199,7 @@ int tool_mmap_user() ** continue execution if no mmap file is open. ** So print message and return fail indicator. */ - fprintf(stderr,"tool_mmap_user(): tool mmap not available\n"); + fprintf(stderr,"tool_mmap_user(): tool mmap not available %s %s\n", strerror(errno), tool_mmap_fname()); tool_mmap_base = (char*)NULL; return(-1); }
Result:
=== ui-smoke.err === tool_mmap_user()------------------------ tool_mmap_user(): tool mmap not available No such file or directory /home/hannes/.tool.mmap poll(): continuing without tool mmap data UI_SMOKE_FAIL: task not ready within 60.0s (last NML error: error return without exception set)There is simply no call to
tool_mmap_creator(), so the file is not created.Funny enough, after the test has failed, the file exists, so a second run of the same tests passes, so you need to delete the file always before running the test, so it fails. Possibly a race condition?
Ehm, you have to go through the tool_mmap_creator() because it is called unconditionally from Task::Task(). That is the constructor for everything task does...
You need to look in the file called
linuxcnc.errin th test directory, which is where also the rtapi_app messages end up in.Ah yes, in
linuxcnc.err:... tool_mmap_creator()------------------------ tool_mmap_user()------------------------ tool_mmap_user()------------------------ ...And in
ui-smoke.errtool_mmap_user()------------------------ tool_mmap_user(): tool mmap not available No such file or directory /home/hannes/.tool.mmapSo next test patch:
diff --git a/src/emc/tooldata/tooldata_mmap.cc b/src/emc/tooldata/tooldata_mmap.cc index 7ba07b48f7..1719a2cb95 100644 --- a/src/emc/tooldata/tooldata_mmap.cc +++ b/src/emc/tooldata/tooldata_mmap.cc @@ -26,6 +26,7 @@ #include "config.h" #include <rtapi_mutex.h> #include "tooldata.hh" +#include <time.h> #define UNEXPECTED_MSG fprintf(stderr,"UNEXPECTED %s %d\n",__FILE__,__LINE__); @@ -143,6 +144,9 @@ int tool_mmap_creator(EMC_TOOL_STAT const * ptr,int random_toolchanger) { static int inited=0; + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + fprintf(stderr,"tool_mmap_creator() %f ------------------------\n", ts.tv_sec + ts.tv_nsec/1000000000.0); if (inited) { fprintf(stderr,"Error: tool_mmap_creator already called BYE\n"); exit(EXIT_FAILURE); @@ -188,6 +192,9 @@ int tool_mmap_user() int fd = open(tool_mmap_fname(), TOOL_MMAP_USER_OPEN_FLAGS, TOOL_MMAP_MODE); + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + fprintf(stderr,"tool_mmap_user() %f------------------------\n", ts.tv_sec + ts.tv_nsec/1000000000.0); if (fd < 0) { /* ** For the LinuxCNC application, tool_mmap_creator() @@ -197,7 +204,7 @@ int tool_mmap_user() ** continue execution if no mmap file is open. ** So print message and return fail indicator. */ - fprintf(stderr,"tool_mmap_user(): tool mmap not available\n"); + fprintf(stderr,"tool_mmap_user(): tool mmap not available %s %s\n", strerror(errno), tool_mmap_fname()); tool_mmap_base = (char*)NULL; return(-1); }
linuxcnc.err:... tool_mmap_creator() 33539.424111 ------------------------ tool_mmap_user() 33539.424343------------------------ tool_mmap_user() 33539.436573------------------------ ...And in
ui-smoke.errtool_mmap_user() 33539.106638------------------------ tool_mmap_user(): tool mmap not available No such file or directory /home/hannes/.tool.mmapLooks to me like
tool_mmap_user()is used beforetool_mmap_creator()is called. Due to this is only an issue once, no one will ever complain, except you isolate the tests.Most likely in
emc/usr_intf/halui.cc. It is started async but milltask may not have fully initialized. Then it will fail to open in halui. That is probably the message you see.Possibly. It might well be that you can only reproduce this by adding a sleep in creator due to the timing on your PC is different.
I can reproduce this without the GUI. The trigger is in
poll()in emcmodule.cc: the firststat.poll()in a process callstool_mmap_user()once, and if~/.tool.mmapdoes not exist yet it sets a staticmmap_available = 0. From then on everypoll()returns NULL without setting an exception, so Python raisesSystemError: error return without exception setforever, and creating a newlinuxcnc.stat()does not help because the flag is process-wide.Fresh HOME, no linuxcnc running:
tool_mmap_user(): tool mmap not available poll(): continuing without tool mmap data 0 error emcStatusBuffer invalid err=3 1 SystemError error return without exception set 2 SystemError error return without exception setui-smoke's
connect_and_wait_ready()polls before task has runtool_mmap_creator(), so it hits the latch and spins until the 60 s timeout. A stale~/.tool.mmapfrom an earlier run hides it, which is why it only shows up isolated. The comment in drive.py calling that SystemError harmless startup noise is mine and wrong.The
touchworkaround gets past it, but the GUI then maps a 0-byte file and would SIGBUS on any tool table access before task extends it. I'll open a small PR makingpoll()retry the attach on each poll until it succeeds, warn once, and keep going without tool data instead of returning NULL (tooldata_get()already handles a NULL base). With that, #4648 should not need the touch.Reacted by hdiethelm- added 3 commits that reference this issue
on Oct 9, 2026 - added a commit that references this issue
on Oct 9, 2026
@grandixximo Probably for you, this is one the reasons the parallel tests failed in CI
Normally, if you run all tests or use LinuxCNC otherwhise, $HOME/.tool.mmap exists. However, in CI if the tests are run isolated, this file does not exist.
->Pass
->Fail