From 5ef749149e85e87371e66c926ce4285c71dc1bc5 Mon Sep 17 00:00:00 2001 From: Hannes Diethelm Date: Tue, 30 Jun 2026 15:18:42 +0200 Subject: [PATCH 1/5] rtapi_app: start command / autostop removed This gives rtapi_app a deterministic behavior. No other changes needed except implementing start / stop in realtime due to all apps run: realtime start at startup realtime stop at exit Autostart is still available with a deprecation message to not break existing setups. But it is done in a different way by forking and then sending the command over the socket. This allows for easy separation into master / client in the future. --- scripts/realtime.in | 22 +++-- src/rtapi/uspace_rtapi_main.cc | 153 +++++++++++++++++++++------------ 2 files changed, 110 insertions(+), 65 deletions(-) diff --git a/scripts/realtime.in b/scripts/realtime.in index bcedea7f3f5..f9daf72d38f 100644 --- a/scripts/realtime.in +++ b/scripts/realtime.in @@ -170,14 +170,20 @@ CheckMem(){ Load(){ CheckKernel - for MOD in $MODULES_LOAD ; do - if ! [ -d "/sys/module/$(basename "$MOD" .ko)" ]; then - $INSMOD "$MOD" || return $? - fi - done - if [ "$DEBUG" != "" ] && [ -w /proc/rtapi/debug ] ; then - echo "$DEBUG" > /proc/rtapi/debug - fi + case $RTPREFIX in + uspace) + rtapi_app start + ;; + (*rtai*) + for MOD in $MODULES_LOAD ; do + if ! [ -d "/sys/module/$(basename "$MOD" .ko)" ]; then + $INSMOD "$MOD" || return $? + fi + done + if [ "$DEBUG" != "" ] && [ -w /proc/rtapi/debug ] ; then + echo "$DEBUG" > /proc/rtapi/debug + fi + esac } CheckLoaded(){ diff --git a/src/rtapi/uspace_rtapi_main.cc b/src/rtapi/uspace_rtapi_main.cc index 9affbd788d3..b9b35f0c57c 100644 --- a/src/rtapi/uspace_rtapi_main.cc +++ b/src/rtapi/uspace_rtapi_main.cc @@ -880,7 +880,10 @@ static int handle_command(const std::vector &args, std::string &out if (args.size() == 0) { return 0; } - if (args.size() == 1 && args[0] == "exit") { + if (args.size() == 1 && args[0] == "start") { + rtapi_print_msg(RTAPI_MSG_ERR, "rtapi_app: start received while running\n"); + return 0; + } else if (args.size() == 1 && args[0] == "exit") { force_exit = 1; return 0; } else if (args.size() >= 2 && args[0] == "load") { @@ -898,7 +901,7 @@ static int handle_command(const std::vector &args, std::string &out } else if (args.size() == 1 && args[0] == "check_rt") { return do_check_rt_cmd(out); } else { - rtapi_print_msg(RTAPI_MSG_ERR, "Unrecognized command starting with %s\n", args[0].c_str()); + rtapi_print_msg(RTAPI_MSG_ERR, "rtapi_app: unrecognized command starting with %s\n", args[0].c_str()); return -1; } } @@ -962,12 +965,12 @@ static bool master_process_socket_command(int fd) { } close(fd1); } - return !force_exit && instance_count > 0; + return !force_exit; } static pthread_t main_thread{}; -static int master(int fd, const std::vector &args) { +static int master(int fd) { is_master = true; main_thread = pthread_self(); int result; @@ -977,22 +980,9 @@ static int master(int fd, const std::vector &args) { return -1; } do_load_cmd("hal_lib", std::vector()); - instance_count = 0; App(); // force rtapi_app to be created - if (args.size()) { - std::string out; - result = handle_command(args, out); - if (result != 0) - goto out; - if (force_exit || instance_count == 0) - goto out; - if (out.length() > 0) { - printf("%s\n", out.c_str()); - } - } //Process commands as long as master should not exit while(master_process_socket_command(fd)); -out: do_unload_cmd("hal_lib"); pthread_cancel(queue_thread); pthread_join(queue_thread, nullptr); @@ -1045,6 +1035,65 @@ static double diff_timespec(const struct timespec *time1, const struct timespec static void raise_net_admin_ambient(void); #endif +static int create_socket(){ + int fd = socket(PF_UNIX, SOCK_STREAM, 0); + if (fd == -1) { + perror("socket"); + return fd; + } + + int enable = 1; + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)); + return fd; +} + +static int start_master(int fd){ + int result = listen(fd, 10); + if (result != 0) { + perror("listen"); + return 1; + } + //Demonize + pid_t pid = fork(); + if (pid < 0){ + perror("fork"); + return 1; + } + if(pid == 0){ + setsid(); // create a new session if we can... + result = master(fd); + exit(result); + }else{ + return 0; + } +} + +static int run_slave_cmd(struct sockaddr_un *addr, int fd, const std::vector &args){ + int result = -1; + struct timespec start, now; + clock_gettime(CLOCK_MONOTONIC, &start); + clock_gettime(CLOCK_MONOTONIC, &now); + srand48(start.tv_sec ^ start.tv_nsec); + while (diff_timespec(&now, &start) < 3.0) { + result = connect(fd, (sockaddr *)addr, sizeof(*addr)); + if (result == 0) + break; + + usleep((useconds_t)(lrand48() % 100000) + 100); //Random sleep min 100us max 100100us + clock_gettime(CLOCK_MONOTONIC, &now); + } + if (result < 0 && errno == ECONNREFUSED) { + fprintf(stderr, "Waited 3 seconds for master. giving up.\n"); + close(fd); + return 1; + } + if (result < 0) { + fprintf(stderr, "connect %s: %s", addr->sun_path, strerror(errno)); + return 1; + } + return slave(fd, args); +} + int main(int argc, char **argv) { if (getuid() == 0) { char *fallback_uid_str = getenv("RTAPI_UID"); @@ -1083,29 +1132,25 @@ int main(int argc, char **argv) { args.push_back(std::string(argv[i])); } -become_master: - int fd = socket(PF_UNIX, SOCK_STREAM, 0); - if (fd == -1) { - perror("socket"); - exit(1); - } - - int enable = 1; - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)); struct sockaddr_un addr; memset(&addr, 0x0, sizeof(addr)); addr.sun_family = AF_UNIX; if (!get_fifo_path_to_addr(&addr)) exit(1); + int fd = create_socket(); + if (fd < 0) { + exit(1); + } + // plus one because we use the abstract namespace, it will show up in // /proc/net/unix prefixed with an @ int result = bind(fd, (sockaddr *)&addr, sizeof(addr)); if (result == 0) { - //If exit is called and master is not running, do not start master - //and exit again + //If exit is called and master is not running, just give a warning if (args.size() == 1 && args[0] == "exit") { + rtapi_print_msg(RTAPI_MSG_ERR, "rtapi_app: exit received while not running\n"); return 0; } //If check_rt is called and master is not running, do not start master @@ -1121,37 +1166,31 @@ int main(int argc, char **argv) { } return ret; } - int result = listen(fd, 10); - if (result != 0) { - perror("listen"); - exit(1); - } - setsid(); // create a new session if we can... - result = master(fd, args); - return result; - } else if (errno == EADDRINUSE) { - struct timespec start, now; - clock_gettime(CLOCK_MONOTONIC, &start); - clock_gettime(CLOCK_MONOTONIC, &now); - srand48(start.tv_sec ^ start.tv_nsec); - while (diff_timespec(&now, &start) < 3.0) { - result = connect(fd, (sockaddr *)&addr, sizeof(addr)); - if (result == 0) - break; - - usleep((useconds_t)(lrand48() % 100000) + 100); //Random sleep min 100us max 100100us - clock_gettime(CLOCK_MONOTONIC, &now); - } - if (result < 0 && errno == ECONNREFUSED) { - fprintf(stderr, "Waited 3 seconds for master. giving up.\n"); + //Start a master on start command + if (args.size() == 1 && args[0] == "start") { + result = start_master(fd); + exit(result); + }else{ + fprintf(stderr, "WARNING: Deprecated: No master found. Use \"realtime start\" to start one.\n" + " A master is started automatically.\n" + " If this appears while using halcmd: Use halrun instead.\n" + " halcmd should only be used with an already running realtime environment.\n" + " halrun creates a realtime environment and tears it down at exit.\n"); + result = start_master(fd); + if (result != 0) { + exit(result); + } + //Need to close and reopen the socket + //It is already bound and master is using it close(fd); - goto become_master; - } - if (result < 0) { - fprintf(stderr, "connect %s: %s", addr.sun_path, strerror(errno)); - exit(1); + int fd = create_socket(); + if (fd < 0) { + exit(1); + } + return run_slave_cmd(&addr, fd, args); } - return slave(fd, args); + } else if (errno == EADDRINUSE) { + return run_slave_cmd(&addr, fd, args); } else { perror("bind"); exit(1); From 44ab47273525043409531487250a46548d1ff9cc Mon Sep 17 00:00:00 2001 From: Hannes Diethelm Date: Tue, 30 Jun 2026 15:22:05 +0200 Subject: [PATCH 2/5] tests: Fixes for rtapi no autostop Due to rtapi_app is started before anything else, the hal-show expected owner id is increased by two. The raster test needs to be started with halrun to have realtime started and stopped properly. --- tests/hal-show/expected | 24 ++++++++++++------------ tests/raster/{test => rastertest.py} | 1 - tests/raster/test.hal | 1 + 3 files changed, 13 insertions(+), 13 deletions(-) rename tests/raster/{test => rastertest.py} (99%) create mode 100644 tests/raster/test.hal diff --git a/tests/hal-show/expected b/tests/hal-show/expected index e4bce169e35..7ecb4551e21 100644 --- a/tests/hal-show/expected +++ b/tests/hal-show/expected @@ -1,11 +1,11 @@ Component Pins: Owner Type Dir Value Name - 8 bit IN FALSE conv-bit-u32.0.in <== net-conv-bit-u32.0.in - 14 float IN 0 conv-float-s32.0.in <== net-conv-float-s32.0.in - 17 s32 IN 0 conv-s32-float.0.in <== net-conv-s32-float.0.in - 20 s64 IN 0 conv-s64-u64.0.in <== net-conv-s64-u64.0.in - 11 u32 IN 0x00000000 conv-u32-bit.0.in <== net-conv-u32-bit.0.in - 23 u64 IN 0x0000000000000000 conv-u64-s64.0.in <== net-conv-u64-s64.0.in + 10 bit IN FALSE conv-bit-u32.0.in <== net-conv-bit-u32.0.in + 16 float IN 0 conv-float-s32.0.in <== net-conv-float-s32.0.in + 19 s32 IN 0 conv-s32-float.0.in <== net-conv-s32-float.0.in + 22 s64 IN 0 conv-s64-u64.0.in <== net-conv-s64-u64.0.in + 13 u32 IN 0x00000000 conv-u32-bit.0.in <== net-conv-u32-bit.0.in + 25 u64 IN 0x0000000000000000 conv-u64-s64.0.in <== net-conv-u64-s64.0.in Signals: Type Value Name (linked to) @@ -36,12 +36,12 @@ s64 0 net-conv-u64-s64.0.out Component Pins: Owner Type Dir Value Name - 8 bit IN TRUE conv-bit-u32.0.in <== net-conv-bit-u32.0.in - 14 float IN 2.147484e+09 conv-float-s32.0.in <== net-conv-float-s32.0.in - 17 s32 IN -2147483648 conv-s32-float.0.in <== net-conv-s32-float.0.in - 20 s64 IN -9223372036854775808 conv-s64-u64.0.in <== net-conv-s64-u64.0.in - 11 u32 IN 0xFFFFFFFF conv-u32-bit.0.in <== net-conv-u32-bit.0.in - 23 u64 IN 0xFFFFFFFFFFFFFFFF conv-u64-s64.0.in <== net-conv-u64-s64.0.in + 10 bit IN TRUE conv-bit-u32.0.in <== net-conv-bit-u32.0.in + 16 float IN 2.147484e+09 conv-float-s32.0.in <== net-conv-float-s32.0.in + 19 s32 IN -2147483648 conv-s32-float.0.in <== net-conv-s32-float.0.in + 22 s64 IN -9223372036854775808 conv-s64-u64.0.in <== net-conv-s64-u64.0.in + 13 u32 IN 0xFFFFFFFF conv-u32-bit.0.in <== net-conv-u32-bit.0.in + 25 u64 IN 0xFFFFFFFFFFFFFFFF conv-u64-s64.0.in <== net-conv-u64-s64.0.in Signals: Type Value Name (linked to) diff --git a/tests/raster/test b/tests/raster/rastertest.py similarity index 99% rename from tests/raster/test rename to tests/raster/rastertest.py index af44c73404c..7ff1c2af394 100755 --- a/tests/raster/test +++ b/tests/raster/rastertest.py @@ -252,7 +252,6 @@ def main(): finally: c.exit() prog.exit() - os.system('halrun -U') return 0 if __name__ == "__main__": diff --git a/tests/raster/test.hal b/tests/raster/test.hal new file mode 100644 index 00000000000..e006f87ed30 --- /dev/null +++ b/tests/raster/test.hal @@ -0,0 +1 @@ +loadusr -w ./rastertest.py From 755b00dcf42dc4d6bf25fd3f31a26dcf1f9566fb Mon Sep 17 00:00:00 2001 From: Hannes Diethelm Date: Wed, 1 Jul 2026 17:28:33 +0200 Subject: [PATCH 3/5] realtime.in: Format script --- scripts/realtime.in | 256 +++++++++++++++++++++++--------------------- 1 file changed, 134 insertions(+), 122 deletions(-) diff --git a/scripts/realtime.in b/scripts/realtime.in index f9daf72d38f..2ed95cf2236 100644 --- a/scripts/realtime.in +++ b/scripts/realtime.in @@ -26,15 +26,17 @@ CheckKernel() { # Shellcheck doesn't know about substitution # shellcheck disable=SC2194 case "@KERNEL_VERS@" in - "") ;; + "") + ;; *) - if [ "$(uname -r)" != "@KERNEL_VERS@" ]; then - cat 1>&2 << EOF + if [ "$(uname -r)" != "@KERNEL_VERS@" ]; then + cat 1>&2 << EOF RTAPI requires the real-time kernel @KERNEL_VERS@ to run. Before running this realtime application, reboot and choose this kernel at the boot menu. EOF - exit 1 - fi + exit 1 + fi + ;; esac } @@ -71,8 +73,8 @@ CheckConfig(){ fi fi if [ -z "$RTAPICONF" ] ; then - echo "Missing rtapi.conf. Check your installation." 1>&2 - exit 1 + echo "Missing rtapi.conf. Check your installation." 1>&2 + exit 1 fi INSMOD="@INSMOD@" RMMOD="@RMMOD@" @@ -94,7 +96,9 @@ CheckConfig(){ MODULES_LOAD= MODULES_UNLOAD= case $RTPREFIX in - uspace) SHM_DEV=/dev/zero;; + uspace) + SHM_DEV=/dev/zero + ;; esac for MOD in $MODULES ; do eval MOD=\${MODPATH_"$MOD"} @@ -108,81 +112,85 @@ CheckConfig(){ MODULES_UNLOAD="$MOD $MODULES_UNLOAD" done case $RTPREFIX in - (*rtai*) - MODULES_LOAD="$MODULES_LOAD $RTLIB_DIR/rtapi$MODULE_EXT $RTLIB_DIR/hal_lib$MODULE_EXT" - MODULES_UNLOAD="hal_lib rtapi $MODULES_UNLOAD" - SHM_DEV=/dev/rtai_shm - ;; - (*) - MODULES_UNLOAD= + *rtai*) + MODULES_LOAD="$MODULES_LOAD $RTLIB_DIR/rtapi$MODULE_EXT $RTLIB_DIR/hal_lib$MODULE_EXT" + MODULES_UNLOAD="hal_lib rtapi $MODULES_UNLOAD" + SHM_DEV=/dev/rtai_shm + ;; + *) + MODULES_UNLOAD= + ;; esac } CheckStatus(){ case $RTPREFIX in - uspace) - if [ -z "$($PS -o stat= -o comm= -C rtapi_app | $GREP -v '^Z')" ]; then - echo rtapi_app is not running - return 1 - else - echo rtapi_app is running - return 0 - fi ;; - *) - # check loaded/unloaded status of modules - unset NOTLOADED - for MOD in $MODULES_UNLOAD ; do - if "$LSMOD" | awk '{print $1}' | $GREP -x "$MOD" >/dev/null ; then - echo "$MOD is loaded" + uspace) + if [ -z "$($PS -o stat= -o comm= -C rtapi_app | $GREP -v '^Z')" ]; then + echo rtapi_app is not running + return 1 else - echo "$MOD is not loaded" - NOTLOADED=NOT + echo rtapi_app is running + return 0 fi - done - if [ -z "$NOTLOADED" ]; then - return 0 - else - return 1 - fi + ;; + *) + # check loaded/unloaded status of modules + unset NOTLOADED + for MOD in $MODULES_UNLOAD ; do + if "$LSMOD" | awk '{print $1}' | $GREP -x "$MOD" >/dev/null ; then + echo "$MOD is loaded" + else + echo "$MOD is not loaded" + NOTLOADED=NOT + fi + done + if [ -z "$NOTLOADED" ]; then + return 0 + else + return 1 + fi + ;; esac } CheckMem(){ # check for user space processes using shared memory if [ -e /dev/mbuff ] ; then - # device file exists, check for processes using it - if $FUSER -s /dev/mbuff 2>/dev/null; then - # at least one process is using it - echo "ERROR: Can't remove RTLinux modules, kill the following process(es) first" - $FUSER -v /dev/mbuff - exit 1 - fi + # device file exists, check for processes using it + if $FUSER -s /dev/mbuff 2>/dev/null; then + # at least one process is using it + echo "ERROR: Can't remove RTLinux modules, kill the following process(es) first" + $FUSER -v /dev/mbuff + exit 1 + fi elif [ -e /dev/rtai_shm ] ; then - # device file exists, check for processes using it - if $FUSER -s /dev/rtai_shm 2>/dev/null; then - # at least one process is using it - echo "ERROR: Can't remove RTAI modules, kill the following process(es) first" - $FUSER -v /dev/rtai_shm - exit 1 - fi + # device file exists, check for processes using it + if $FUSER -s /dev/rtai_shm 2>/dev/null; then + # at least one process is using it + echo "ERROR: Can't remove RTAI modules, kill the following process(es) first" + $FUSER -v /dev/rtai_shm + exit 1 + fi fi } Load(){ CheckKernel case $RTPREFIX in - uspace) - rtapi_app start - ;; - (*rtai*) - for MOD in $MODULES_LOAD ; do - if ! [ -d "/sys/module/$(basename "$MOD" .ko)" ]; then - $INSMOD "$MOD" || return $? - fi - done - if [ "$DEBUG" != "" ] && [ -w /proc/rtapi/debug ] ; then - echo "$DEBUG" > /proc/rtapi/debug - fi + uspace) + rtapi_app start + ;; + *rtai*) + for MOD in $MODULES_LOAD ; do + if ! [ -d "/sys/module/$(basename "$MOD" .ko)" ]; then + $INSMOD "$MOD" || return $? + fi + done + if [ "$DEBUG" != "" ] && [ -w /proc/rtapi/debug ] ; then + echo "$DEBUG" > /proc/rtapi/debug + fi + ;; esac } @@ -202,29 +210,32 @@ CheckLoaded(){ Unload(){ CheckKernel + case $RTPREFIX in - uspace) - rtapi_app exit + uspace) + rtapi_app exit - # wait 5 seconds for rtapi_app to die and be reaped by its parent - START=$SECONDS - local NPROCS - while [ 5 -gt $((SECONDS-START)) ]; do + # wait 5 seconds for rtapi_app to die and be reaped by its parent + START=$SECONDS + local NPROCS + while [ 5 -gt $((SECONDS-START)) ]; do + NPROCS=$(ps -C rtapi_app -o stat= -o comm= | $GREP -v '^Z' | wc -l) + if [ "$NPROCS" -eq 0 ]; then + break + fi + sleep 0.1 + done NPROCS=$(ps -C rtapi_app -o stat= -o comm= | $GREP -v '^Z' | wc -l) - if [ "$NPROCS" -eq 0 ]; then - break + if [ "$NPROCS" -gt 0 ]; then + echo "ERROR: rtapi_app failed to die" 1>&2 fi - sleep 0.1 - done - NPROCS=$(ps -C rtapi_app -o stat= -o comm= | $GREP -v '^Z' | wc -l) - if [ "$NPROCS" -gt 0 ]; then - echo "ERROR: rtapi_app failed to die" 1>&2 - fi - ipcrm -M 0x48414c32 2>/dev/null ;# HAL_KEY - ipcrm -M 0x90280A48 2>/dev/null ;# RTAPI_KEY - ipcrm -M 0x48484c34 2>/dev/null ;# UUID_KEY + ipcrm -M 0x48414c32 2>/dev/null ;# HAL_KEY + ipcrm -M 0x90280A48 2>/dev/null ;# RTAPI_KEY + ipcrm -M 0x48484c34 2>/dev/null ;# UUID_KEY + ;; esac + for module in $MODULES_UNLOAD ; do $RMMOD "$module" done @@ -233,12 +244,13 @@ Unload(){ Verify(){ HAS_REALTIME=false case $RTPREFIX in - uspace) - rtapi_app check_rt && HAS_REALTIME=true - ;; - (*rtai*) - echo "RTAI" - HAS_REALTIME=true + uspace) + rtapi_app check_rt && HAS_REALTIME=true + ;; + *rtai*) + echo "RTAI" + HAS_REALTIME=true + ;; esac if [ $HAS_REALTIME = true ]; then @@ -252,50 +264,50 @@ CheckUnloaded(){ # checks to see if all modules were unloaded STATUS= for module in $MODULES_UNLOAD ; do - # check to see if the module is installed - if "$LSMOD" | awk '{print $1}' | $GREP -x "$module" >/dev/null ; then - echo "ERROR: Could not unload '$module'" - STATUS=error - fi + # check to see if the module is installed + if "$LSMOD" | awk '{print $1}' | $GREP -x "$module" >/dev/null ; then + echo "ERROR: Could not unload '$module'" + STATUS=error + fi done if [ -n "$STATUS" ] ; then - exit 1 + exit 1 fi } CMD=$1 case "$CMD" in - start|load) - CheckConfig - Load || exit $? - CheckLoaded - ;; - restart|force-reload) - CheckConfig - CheckMem - Unload - CheckUnloaded - Load || exit $? - CheckLoaded - ;; - stop|unload) - CheckConfig - CheckMem - Unload || exit $? - ;; - status) - CheckConfig - CheckStatus || exit $? - ;; - verify) - CheckConfig - Verify || exit $? - ;; - *) - echo "Usage: $0 {start|load|stop|unload|restart|force-reload|status|verify}" >&2 - exit 1 - ;; + start|load) + CheckConfig + Load || exit $? + CheckLoaded + ;; + restart|force-reload) + CheckConfig + CheckMem + Unload + CheckUnloaded + Load || exit $? + CheckLoaded + ;; + stop|unload) + CheckConfig + CheckMem + Unload || exit $? + ;; + status) + CheckConfig + CheckStatus || exit $? + ;; + verify) + CheckConfig + Verify || exit $? + ;; + *) + echo "Usage: $0 {start|load|stop|unload|restart|force-reload|status|verify}" >&2 + exit 1 + ;; esac exit 0 From 76fccf9aea5f520b197d75b4e36528e66557aac8 Mon Sep 17 00:00:00 2001 From: Hannes Diethelm Date: Wed, 1 Jul 2026 17:57:09 +0200 Subject: [PATCH 4/5] realtime.in: Fix shellcheck issue --- scripts/realtime.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/realtime.in b/scripts/realtime.in index 2ed95cf2236..75dd12231a0 100644 --- a/scripts/realtime.in +++ b/scripts/realtime.in @@ -101,7 +101,7 @@ CheckConfig(){ ;; esac for MOD in $MODULES ; do - eval MOD=\${MODPATH_"$MOD"} + eval MOD="\${MODPATH_${MOD}}" if [ -z "$MOD" ]; then continue; fi if [ -L "$MOD" ]; then MOD=${MOD%/*}/$(readlink "$MOD") From 3a78036572bfee5835fdc1081270f26f3d20364c Mon Sep 17 00:00:00 2001 From: Hannes Diethelm Date: Thu, 2 Jul 2026 15:16:38 +0200 Subject: [PATCH 5/5] latency-histogram: Enable realtime start for non RTAI It was only active for RTAI. Do realtime start in forground for RTAI. Additionally, simplify realtime verify. --- scripts/latency-histogram | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/scripts/latency-histogram b/scripts/latency-histogram index b52d896a46f..a2dc38abb72 100755 --- a/scripts/latency-histogram +++ b/scripts/latency-histogram @@ -36,10 +36,10 @@ proc set_defaults {} { set ::LH(start) [clock seconds] # don't include glxgears, error suffices program_check {halrun halcmd lsmod pgrep pkill hostname} + set ::LH(realtime) [exec linuxcnc_var REALTIME] + program_check $::LH(realtime) if {[string first rtai [string tolower $::tcl_platform(osVersion)]] >=0} { set ::LH(rtai) rtai - set ::LH(realtime) [exec linuxcnc_var REALTIME] - program_check $::LH(realtime) } set ::LH(use_x) 1 @@ -314,9 +314,13 @@ proc load_packages {} { } if [info exists ::LH(rtai)] { - exec $::LH(realtime) start & + exec $::LH(realtime) start >@stdout 2>@stderr progress "Delay for realtime startup" after 1000 ;# wait to load Hal package + } else { + exec $::LH(realtime) start >@stdout 2>@stderr + #No need to exec in background and wait + #uspace realtime has next to no startup delay } # augment ::auto_path for special case: @@ -343,12 +347,10 @@ proc rt_status_items {} { # realtime: type from 'realtime verify' stdout, yes/no from its exit status. set rt_text "no realtime" set rt_ok 0 - if {![catch {exec linuxcnc_var REALTIME} rt]} { - if {![catch {open [list | $rt verify 2> /dev/null] r} chan]} { - set out [string trim [read $chan]] - set rt_ok [expr {![catch {close $chan}]}] - if {$out ne ""} {set rt_text $out} - } + if {![catch {open [list | $::LH(realtime) verify 2> /dev/null] r} chan]} { + set out [string trim [read $chan]] + set rt_ok [expr {![catch {close $chan}]}] + if {$out ne ""} {set rt_text $out} } lappend items [list $rt_text [expr {$rt_ok ? "" : $red}]]