@@ -922,6 +922,65 @@ static double diff_timespec(const struct timespec *time1, const struct timespec
922922static void raise_net_admin_ambient (void );
923923#endif
924924
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+
925984int main (int argc, char **argv) {
926985 if (getuid () == 0 ) {
927986 char *fallback_uid_str = getenv (" RTAPI_UID" );
@@ -960,20 +1019,17 @@ int main(int argc, char **argv) {
9601019 args.push_back (std::string (argv[i]));
9611020 }
9621021
963- int fd = socket (PF_UNIX , SOCK_STREAM , 0 );
964- if (fd == -1 ) {
965- perror (" socket" );
966- exit (1 );
967- }
968-
969- int enable = 1 ;
970- setsockopt (fd, SOL_SOCKET , SO_REUSEADDR , &enable, sizeof (enable));
9711022 struct sockaddr_un addr;
9721023 memset (&addr, 0x0 , sizeof (addr));
9731024 addr.sun_family = AF_UNIX ;
9741025 if (!get_fifo_path_to_addr (&addr))
9751026 exit (1 );
9761027
1028+ int fd = create_socket ();
1029+ if (fd < 0 ) {
1030+ exit (1 );
1031+ }
1032+
9771033 // plus one because we use the abstract namespace, it will show up in
9781034 // /proc/net/unix prefixed with an @
9791035 int result = bind (fd, (sockaddr *)&addr, sizeof (addr));
@@ -994,48 +1050,24 @@ int main(int argc, char **argv) {
9941050 }
9951051 // Start a master on start command
9961052 if (args.size () == 1 && args[0 ] == " start" ) {
997- int result = listen (fd, 10 );
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 automaticaly.\n " );
1058+ result = start_master (fd);
9981059 if (result != 0 ) {
999- perror (" listen" );
1000- exit (1 );
1060+ exit (result);
10011061 }
1002- // Demonize
1003- pid_t pid = fork ();
1004- if (pid < 0 ){
1005- perror (" fork" );
1062+ close (fd); // Need to close the socket, it is already bound and master is using it
1063+ int fd = create_socket ();
1064+ if (fd < 0 ) {
10061065 exit (1 );
10071066 }
1008- if (pid == 0 ){
1009- setsid (); // create a new session if we can...
1010- result = master (fd);
1011- }
1012- return result;
1067+ return run_slave_cmd (&addr, fd, args);
10131068 }
1014- fprintf (stderr, " error: No master found. Use realtime start to start one.\n " );
1015- exit (1 );
10161069 } else if (errno == EADDRINUSE ) {
1017- struct timespec start, now;
1018- clock_gettime (CLOCK_MONOTONIC , &start);
1019- clock_gettime (CLOCK_MONOTONIC , &now);
1020- srand48 (start.tv_sec ^ start.tv_nsec );
1021- while (diff_timespec (&now, &start) < 3.0 ) {
1022- result = connect (fd, (sockaddr *)&addr, sizeof (addr));
1023- if (result == 0 )
1024- break ;
1025-
1026- usleep ((useconds_t )(lrand48 () % 100000 ) + 100 ); // Random sleep min 100us max 100100us
1027- clock_gettime (CLOCK_MONOTONIC , &now);
1028- }
1029- if (result < 0 && errno == ECONNREFUSED ) {
1030- fprintf (stderr, " Waited 3 seconds for master. giving up.\n " );
1031- close (fd);
1032- exit (1 );
1033- }
1034- if (result < 0 ) {
1035- fprintf (stderr, " connect %s: %s" , addr.sun_path , strerror (errno));
1036- exit (1 );
1037- }
1038- return slave (fd, args);
1070+ return run_slave_cmd (&addr, fd, args);
10391071 } else {
10401072 perror (" bind" );
10411073 exit (1 );
0 commit comments