From 6c13d05eae563fcee73a761996329f27e153c02c Mon Sep 17 00:00:00 2001 From: Luca Toniolo <10792599+grandixximo@users.noreply.github.com> Date: Fri, 7 Aug 2026 22:46:45 +1000 Subject: [PATCH] halscope: fix "loadrt scope_rt failed" when reopening the scope Closing halscope leaves scope_rt loaded, so every launch after the first has to detect that the realtime part is already there and skip the loadrt. That detection broke in d88d10db8f: the funct lookup halpr_find_funct_by_name("scope.sample") was replaced with the component lookup hal_comp_by_name("scope.sample", NULL). No component is named "scope.sample" (the component is "scope_rt", "scope.sample" is the funct it exports), so the lookup always returns -ENOENT and halscope always runs "halcmd loadrt scope_rt". On the second launch that loadrt fails because scope_rt is already loaded, and halscope exits immediately with "loadrt scope_rt failed". From a GUI such as AXIS ("Machine" > "Hal Scope") the window simply never appears again until LinuxCNC is restarted. Look the funct up with hal_list_funct() instead, the same way scope_horiz.c already does, which restores the original semantics. --- src/hal/utils/scope.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/hal/utils/scope.c b/src/hal/utils/scope.c index 45327d5ced4..dd96030ee29 100644 --- a/src/hal/utils/scope.c +++ b/src/hal/utils/scope.c @@ -99,6 +99,15 @@ static void exit_on_signal(int signum) { exit(1); } +/* callback for hal_list_funct(), matches a function by name */ +static int find_funct_cb(hal_query_t *q, void *arg) +{ + if (!strcmp((const char *)arg, q->name)) { + return 1; /* positive, break the loop without error */ + } + return 0; +} + /* Read just the SAMPLES value from config file before loading scope_rt */ static int read_samples_from_config(const char *filename) { @@ -199,8 +208,9 @@ int main(int argc, gchar * argv[]) return -1; } - int rv = hal_comp_by_name("scope.sample", NULL); - if (-ENOENT == rv) { + hal_query_t qf = {}; + int rv = hal_list_funct(&qf, find_funct_cb, (void *)"scope.sample"); + if (0 == rv) { char buf[1000]; snprintf(buf, sizeof(buf), EMC2_BIN_DIR "/halcmd loadrt scope_rt num_samples=%d", num_samples); @@ -209,12 +219,15 @@ int main(int argc, gchar * argv[]) hal_exit(comp_id); exit(1); } - } else { + } else if (rv > 0) { /* scope_rt already loaded - we'll check if sample count matches later */ - if(0 == rv) - rtapi_print_msg(RTAPI_MSG_DBG, "SCOPE: scope_rt already loaded, requested %d samples\n", num_samples); - else - rtapi_print_msg(RTAPI_MSG_DBG, "SCOPE: hal_comp_by_name() returned error %d\n", rv); + rtapi_print_msg(RTAPI_MSG_DBG, "SCOPE: scope_rt already loaded, requested %d samples\n", num_samples); + } else { + /* the query itself failed, we cannot tell whether scope_rt is loaded + and must not try to load it again */ + rtapi_print_msg(RTAPI_MSG_ERR, "SCOPE: ERROR: hal_list_funct() returned error %d (%s)\n", rv, hal_strerror(rv)); + hal_exit(comp_id); + exit(1); } /* set up a shared memory region for the scope data */ shm_id = rtapi_shmem_new(SCOPE_SHM_KEY, comp_id, sizeof(scope_shm_control_t));