Skip to content

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

Description

@hdiethelm

@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.

touch $HOME/.tool.mmap
scripts/runtests -p tests/ui-smoke/qtdragon

->Pass

rm $HOME/.tool.mmap
scripts/runtests -p tests/ui-smoke/qtdragon

->Fail

Activity

  1. BsAtHome commented on Oct 8, 2026

    @BsAtHome
    Contributor

    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 running
    

    It is also problematic that the mmap backing file is never cleaned up when things seem to run normally.

  2. BsAtHome commented on Oct 8, 2026

    @BsAtHome
    Contributor

    The error is in:

    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_NOFOLLOW can be problematic as CI most likely redirects things bit.

  3. hdiethelm commented on Oct 8, 2026

    @hdiethelm
    ContributorAuthor

    Sorry to not hint directly to this file. There are two functions:
    tool_mmap_user() which opens the file and expect it exists and tool_mmap_creator() which creates it. Looks like only tool_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.

  4. BsAtHome commented on Oct 8, 2026

    @BsAtHome
    Contributor

    You won't even reach the tool_mmap_user() if the tool_mmap_creator() fails to create the file. It simply executes an exit() and then all things fall apart.

  5. BsAtHome commented on Oct 8, 2026

    @BsAtHome
    Contributor

    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.

  6. hdiethelm commented on Oct 8, 2026

    @hdiethelm
    ContributorAuthor

    In CI, I got the error tool_mmap_user(): tool mmap not available which is from tool_mmap_user(), so I think tool_mmap_creator() is not even called.
    Quick and dirty workaround: 454a737
    Now it fails somewhere else, probably unrelated to this issue.

  7. BsAtHome commented on Oct 8, 2026

    @BsAtHome
    Contributor

    Can you check something for me then...

    In tool_mmap_user() you hit the fprintf() and that means we don't see the errno. Change fprintf(stderr, into perror( and we should be see why it fails.

  8. hdiethelm commented on Oct 8, 2026

    @hdiethelm
    ContributorAuthor

    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.

  9. hdiethelm commented on Oct 8, 2026

    @hdiethelm
    ContributorAuthor

    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?

  10. BsAtHome commented on Oct 8, 2026

    @BsAtHome
    Contributor

    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.err in th test directory, which is where also the rtapi_app messages end up in.

  11. hdiethelm commented on Oct 8, 2026

    @hdiethelm
    ContributorAuthor

    Ah yes, in linuxcnc.err:

    ...
    tool_mmap_creator()------------------------
    tool_mmap_user()------------------------
    tool_mmap_user()------------------------
    ...
    

    And in ui-smoke.err

    tool_mmap_user()------------------------
    tool_mmap_user(): tool mmap not available No such file or directory /home/hannes/.tool.mmap
    

    So 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.err

    tool_mmap_user() 33539.106638------------------------
    tool_mmap_user(): tool mmap not available No such file or directory /home/hannes/.tool.mmap
    

    Looks to me like tool_mmap_user() is used before tool_mmap_creator() is called. Due to this is only an issue once, no one will ever complain, except you isolate the tests.

  12. BsAtHome commented on Oct 8, 2026

    @BsAtHome
    Contributor

    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.

  13. hdiethelm commented on Oct 8, 2026

    @hdiethelm
    ContributorAuthor

    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.

  14. grandixximo commented on Oct 9, 2026

    @grandixximo
    Contributor

    I can reproduce this without the GUI. The trigger is in poll() in emcmodule.cc: the first stat.poll() in a process calls tool_mmap_user() once, and if ~/.tool.mmap does not exist yet it sets a static mmap_available = 0. From then on every poll() returns NULL without setting an exception, so Python raises SystemError: error return without exception set forever, and creating a new linuxcnc.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 set
    

    ui-smoke's connect_and_wait_ready() polls before task has run tool_mmap_creator(), so it hits the latch and spins until the 60 s timeout. A stale ~/.tool.mmap from 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 touch workaround 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 making poll() 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.

  15. added 3 commits that reference this issue on Oct 9, 2026
    f8f2563
    8c49b76
    e0a1100
  16. added a commit that references this issue on Oct 9, 2026
    83b5368
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions