diff --git a/scripts/realtime.in b/scripts/realtime.in index 286d57e0aee..c2f741d0382 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,10 +96,12 @@ 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"} + eval MOD="\${MODPATH_${MOD}}" if [ -z "$MOD" ]; then continue; fi if [ -L "$MOD" ]; then MOD=${MOD%/*}/$(readlink "$MOD") @@ -108,76 +112,86 @@ 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 - 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(){ @@ -196,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 @@ -227,11 +244,12 @@ Unload(){ Verify(){ HAS_REALTIME=false case $RTPREFIX in - uspace) - rtapi_app check_rt && HAS_REALTIME=true - ;; - (*rtai*) - HAS_REALTIME=true + uspace) + rtapi_app check_rt && HAS_REALTIME=true + ;; + *rtai*) + HAS_REALTIME=true + ;; esac if [ $HAS_REALTIME = true ]; then @@ -247,50 +265,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 diff --git a/src/rtapi/uspace_rtapi_main.cc b/src/rtapi/uspace_rtapi_main.cc index 3f9bda20ecb..d0732b3c64b 100644 --- a/src/rtapi/uspace_rtapi_main.cc +++ b/src/rtapi/uspace_rtapi_main.cc @@ -772,7 +772,10 @@ static int handle_command(const std::vector &args) { 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") { @@ -790,7 +793,7 @@ static int handle_command(const std::vector &args) { } else if (args.size() == 1 && args[0] == "check_rt") { return do_check_rt_cmd(); } 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; } } @@ -849,12 +852,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; @@ -864,18 +867,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()) { - result = handle_command(args); - if (result != 0) - goto out; - if (force_exit || instance_count == 0) - goto out; - } //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); @@ -928,6 +922,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"); @@ -966,29 +1019,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 @@ -999,37 +1048,31 @@ int main(int argc, char **argv) { if (args.size() == 1 && args[0] == "check_rt") { return do_check_rt_cmd(); } - 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); 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