Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions scripts/realtime.in
Original file line number Diff line number Diff line change
Expand Up @@ -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(){
Expand Down
144 changes: 91 additions & 53 deletions src/rtapi/uspace_rtapi_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -772,7 +772,10 @@ static int handle_command(const std::vector<std::string> &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") {
Expand All @@ -790,7 +793,7 @@ static int handle_command(const std::vector<std::string> &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;
}
}
Expand Down Expand Up @@ -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<std::string> &args) {
static int master(int fd) {
is_master = true;
main_thread = pthread_self();
int result;
Expand All @@ -864,18 +867,9 @@ static int master(int fd, const std::vector<std::string> &args) {
return -1;
}
do_load_cmd("hal_lib", std::vector<std::string>());
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);
Expand Down Expand Up @@ -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<std::string> &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");
Expand Down Expand Up @@ -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
Expand All @@ -999,37 +1048,26 @@ 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);
//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 automaticaly.\n");
result = start_master(fd);
if (result != 0) {
exit(result);
}
close(fd); //Need to close the socket, it is already bound and master is using it
int fd = create_socket();
if (fd < 0) {
exit(1);
}
return run_slave_cmd(&addr, fd, args);
}
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");
close(fd);
goto become_master;
}
if (result < 0) {
fprintf(stderr, "connect %s: %s", addr.sun_path, strerror(errno));
exit(1);
}
return slave(fd, args);
return run_slave_cmd(&addr, fd, args);
} else {
perror("bind");
exit(1);
Expand Down
24 changes: 12 additions & 12 deletions tests/hal-show/expected
Original file line number Diff line number Diff line change
@@ -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)
Expand Down Expand Up @@ -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)
Expand Down
35 changes: 29 additions & 6 deletions tests/raster/test
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
import hal
import time
import os
import subprocess
from raster import *

theta = 0.005
Expand Down Expand Up @@ -193,10 +193,19 @@ def main():

prog = RasterProgrammer("programmer")

#instantiate the raster component,
#add it to a thread and link all signals from
#the test component here
assert os.system('halcmd -f raster.hal') == 0, "raster.hal script failed"
#instantiate the raster component
#use interactive mode to be have the hal running
#while needed and exit with writing "exit" at the end
halrun = subprocess.Popen(["halrun", "-Is", "raster.hal"], stdin=subprocess.PIPE)
#Test the last connection added in raster.hal
#to determine if hal is up and running
deadline = time.time() + 5
while time.time() < deadline:
if hal.pin_has_writer("test.fraction"):
break
time.sleep(0.01)
else:
raise RuntimeError("raster.hal did not come up within 5s")

testInvalidOffset(prog, pin)
testInvalidBPP(prog, pin)
Expand Down Expand Up @@ -252,7 +261,21 @@ def main():
finally:
c.exit()
prog.exit()
os.system('halrun -U')
try:
try:
halrun.communicate(input=b"exit\n", timeout=5)
except subprocess.TimeoutExpired:
halrun.kill()
halrun.communicate()
exit_status = halrun.returncode
if exit_status == 0:
return 0
else:
print("Halrun failed, exit status " + str(exit_status))
return 1
except Exception as e:
print("error: Test failed: {}".format(traceback.format_exc()))
return 1
return 0

if __name__ == "__main__":
Expand Down
Loading