Skip to content

Commit cf57422

Browse files
committed
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.
1 parent 78817f3 commit cf57422

2 files changed

Lines changed: 110 additions & 61 deletions

File tree

scripts/realtime.in

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -170,14 +170,20 @@ CheckMem(){
170170

171171
Load(){
172172
CheckKernel
173-
for MOD in $MODULES_LOAD ; do
174-
if ! [ -d "/sys/module/$(basename "$MOD" .ko)" ]; then
175-
$INSMOD "$MOD" || return $?
176-
fi
177-
done
178-
if [ "$DEBUG" != "" ] && [ -w /proc/rtapi/debug ] ; then
179-
echo "$DEBUG" > /proc/rtapi/debug
180-
fi
173+
case $RTPREFIX in
174+
uspace)
175+
rtapi_app start
176+
;;
177+
(*rtai*)
178+
for MOD in $MODULES_LOAD ; do
179+
if ! [ -d "/sys/module/$(basename "$MOD" .ko)" ]; then
180+
$INSMOD "$MOD" || return $?
181+
fi
182+
done
183+
if [ "$DEBUG" != "" ] && [ -w /proc/rtapi/debug ] ; then
184+
echo "$DEBUG" > /proc/rtapi/debug
185+
fi
186+
esac
181187
}
182188

183189
CheckLoaded(){

src/rtapi/uspace_rtapi_main.cc

Lines changed: 96 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -772,7 +772,10 @@ static int handle_command(const std::vector<std::string> &args) {
772772
if (args.size() == 0) {
773773
return 0;
774774
}
775-
if (args.size() == 1 && args[0] == "exit") {
775+
if (args.size() == 1 && args[0] == "start") {
776+
rtapi_print_msg(RTAPI_MSG_ERR, "rtapi_app: start received while running\n");
777+
return 0;
778+
} else if (args.size() == 1 && args[0] == "exit") {
776779
force_exit = 1;
777780
return 0;
778781
} else if (args.size() >= 2 && args[0] == "load") {
@@ -790,7 +793,7 @@ static int handle_command(const std::vector<std::string> &args) {
790793
} else if (args.size() == 1 && args[0] == "check_rt") {
791794
return do_check_rt_cmd();
792795
} else {
793-
rtapi_print_msg(RTAPI_MSG_ERR, "Unrecognized command starting with %s\n", args[0].c_str());
796+
rtapi_print_msg(RTAPI_MSG_ERR, "rtapi_app: unrecognized command starting with %s\n", args[0].c_str());
794797
return -1;
795798
}
796799
}
@@ -849,12 +852,12 @@ static bool master_process_socket_command(int fd) {
849852
}
850853
close(fd1);
851854
}
852-
return !force_exit && instance_count > 0;
855+
return !force_exit;
853856
}
854857

855858
static pthread_t main_thread{};
856859

857-
static int master(int fd, const std::vector<std::string> &args) {
860+
static int master(int fd) {
858861
is_master = true;
859862
main_thread = pthread_self();
860863
int result;
@@ -864,18 +867,9 @@ static int master(int fd, const std::vector<std::string> &args) {
864867
return -1;
865868
}
866869
do_load_cmd("hal_lib", std::vector<std::string>());
867-
instance_count = 0;
868870
App(); // force rtapi_app to be created
869-
if (args.size()) {
870-
result = handle_command(args);
871-
if (result != 0)
872-
goto out;
873-
if (force_exit || instance_count == 0)
874-
goto out;
875-
}
876871
//Process commands as long as master should not exit
877872
while(master_process_socket_command(fd));
878-
out:
879873
do_unload_cmd("hal_lib");
880874
pthread_cancel(queue_thread);
881875
pthread_join(queue_thread, nullptr);
@@ -928,6 +922,65 @@ static double diff_timespec(const struct timespec *time1, const struct timespec
928922
static void raise_net_admin_ambient(void);
929923
#endif
930924

925+
static int create_socket(){
926+
int fd = socket(PF_UNIX, SOCK_STREAM, 0);
927+
if (fd == -1) {
928+
perror("socket");
929+
return fd;
930+
}
931+
932+
int enable = 1;
933+
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));
934+
return fd;
935+
}
936+
937+
static int start_master(int fd){
938+
int result = listen(fd, 10);
939+
if (result != 0) {
940+
perror("listen");
941+
return 1;
942+
}
943+
//Demonize
944+
pid_t pid = fork();
945+
if (pid < 0){
946+
perror("fork");
947+
return 1;
948+
}
949+
if(pid == 0){
950+
setsid(); // create a new session if we can...
951+
result = master(fd);
952+
exit(result);
953+
}else{
954+
return 0;
955+
}
956+
}
957+
958+
static int run_slave_cmd(struct sockaddr_un *addr, int fd, const std::vector<std::string> &args){
959+
int result = -1;
960+
struct timespec start, now;
961+
clock_gettime(CLOCK_MONOTONIC, &start);
962+
clock_gettime(CLOCK_MONOTONIC, &now);
963+
srand48(start.tv_sec ^ start.tv_nsec);
964+
while (diff_timespec(&now, &start) < 3.0) {
965+
result = connect(fd, (sockaddr *)addr, sizeof(*addr));
966+
if (result == 0)
967+
break;
968+
969+
usleep((useconds_t)(lrand48() % 100000) + 100); //Random sleep min 100us max 100100us
970+
clock_gettime(CLOCK_MONOTONIC, &now);
971+
}
972+
if (result < 0 && errno == ECONNREFUSED) {
973+
fprintf(stderr, "Waited 3 seconds for master. giving up.\n");
974+
close(fd);
975+
return 1;
976+
}
977+
if (result < 0) {
978+
fprintf(stderr, "connect %s: %s", addr->sun_path, strerror(errno));
979+
return 1;
980+
}
981+
return slave(fd, args);
982+
}
983+
931984
int main(int argc, char **argv) {
932985
if (getuid() == 0) {
933986
char *fallback_uid_str = getenv("RTAPI_UID");
@@ -966,29 +1019,25 @@ int main(int argc, char **argv) {
9661019
args.push_back(std::string(argv[i]));
9671020
}
9681021

969-
become_master:
970-
int fd = socket(PF_UNIX, SOCK_STREAM, 0);
971-
if (fd == -1) {
972-
perror("socket");
973-
exit(1);
974-
}
975-
976-
int enable = 1;
977-
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));
9781022
struct sockaddr_un addr;
9791023
memset(&addr, 0x0, sizeof(addr));
9801024
addr.sun_family = AF_UNIX;
9811025
if (!get_fifo_path_to_addr(&addr))
9821026
exit(1);
9831027

1028+
int fd = create_socket();
1029+
if (fd < 0) {
1030+
exit(1);
1031+
}
1032+
9841033
// plus one because we use the abstract namespace, it will show up in
9851034
// /proc/net/unix prefixed with an @
9861035
int result = bind(fd, (sockaddr *)&addr, sizeof(addr));
9871036

9881037
if (result == 0) {
989-
//If exit is called and master is not running, do not start master
990-
//and exit again
1038+
//If exit is called and master is not running, just give a warning
9911039
if (args.size() == 1 && args[0] == "exit") {
1040+
rtapi_print_msg(RTAPI_MSG_ERR, "rtapi_app: exit received while not running\n");
9921041
return 0;
9931042
}
9941043
//If check_rt is called and master is not running, do not start master
@@ -999,37 +1048,31 @@ int main(int argc, char **argv) {
9991048
if (args.size() == 1 && args[0] == "check_rt") {
10001049
return do_check_rt_cmd();
10011050
}
1002-
int result = listen(fd, 10);
1003-
if (result != 0) {
1004-
perror("listen");
1005-
exit(1);
1006-
}
1007-
setsid(); // create a new session if we can...
1008-
result = master(fd, args);
1009-
return result;
1010-
} else if (errno == EADDRINUSE) {
1011-
struct timespec start, now;
1012-
clock_gettime(CLOCK_MONOTONIC, &start);
1013-
clock_gettime(CLOCK_MONOTONIC, &now);
1014-
srand48(start.tv_sec ^ start.tv_nsec);
1015-
while (diff_timespec(&now, &start) < 3.0) {
1016-
result = connect(fd, (sockaddr *)&addr, sizeof(addr));
1017-
if (result == 0)
1018-
break;
1019-
1020-
usleep((useconds_t)(lrand48() % 100000) + 100); //Random sleep min 100us max 100100us
1021-
clock_gettime(CLOCK_MONOTONIC, &now);
1022-
}
1023-
if (result < 0 && errno == ECONNREFUSED) {
1024-
fprintf(stderr, "Waited 3 seconds for master. giving up.\n");
1051+
//Start a master on start command
1052+
if (args.size() == 1 && args[0] == "start") {
1053+
result = start_master(fd);
1054+
exit(result);
1055+
}else{
1056+
fprintf(stderr, "WARNING: Deprecated: No master found. Use \"realtime start\" to start one.\n"
1057+
" A master is started automatically.\n"
1058+
" If this appears while using halcmd: Use halrun instead.\n"
1059+
" halcmd should only be used with an already running realtime environment.\n"
1060+
" halrun creates a realtime environment and tears it down at exit.\n");
1061+
result = start_master(fd);
1062+
if (result != 0) {
1063+
exit(result);
1064+
}
1065+
//Need to close and reopen the socket
1066+
//It is already bound and master is using it
10251067
close(fd);
1026-
goto become_master;
1027-
}
1028-
if (result < 0) {
1029-
fprintf(stderr, "connect %s: %s", addr.sun_path, strerror(errno));
1030-
exit(1);
1068+
int fd = create_socket();
1069+
if (fd < 0) {
1070+
exit(1);
1071+
}
1072+
return run_slave_cmd(&addr, fd, args);
10311073
}
1032-
return slave(fd, args);
1074+
} else if (errno == EADDRINUSE) {
1075+
return run_slave_cmd(&addr, fd, args);
10331076
} else {
10341077
perror("bind");
10351078
exit(1);

0 commit comments

Comments
 (0)