@@ -62,7 +62,7 @@ constexpr std::array<int, 10> TERM_SIGNALS = {SIGINT,
6262 */
6363int main (int argc, char **argv) {
6464 const std::string exe_name = std::filesystem::path (*argv).filename ().string ();
65- cxxopts::Options options (exe_name, " Read instructions from stdin and write them to a modbus shared memory" );
65+ cxxopts::Options options (exe_name, " Read instructions from stdin and write them to a Modbus shared memory" );
6666
6767 auto exit_usage = [&exe_name]() {
6868 std::cerr << " Use '" << exe_name << " --help' for more information.\n " ;
@@ -115,6 +115,11 @@ int main(int argc, char **argv) {
115115 options.add_options (" shared memory" )(" semaphore-timeout" ,
116116 " maximum time (in seconds) to wait for semaphore (default: 0.1)" ,
117117 cxxopts::value<double >()->default_value (" 0.1" ));
118+ options.add_options (" shared_memory" )(
119+ " pid" ,
120+ " terminate application if application with given pid is terminated. Provide "
121+ " the pid of the Modbus client to terminate when the Modbus client is terminated." ,
122+ cxxopts::value<pid_t >());
118123
119124 // parse arguments
120125 cxxopts::ParseResult args;
@@ -129,7 +134,7 @@ int main(int argc, char **argv) {
129134 std::cout << " Data input format: reg_type:address:value[:data_type]" << ' \n ' ;
130135 std::cout << " reg_type : modbus register type: [do|di|ao|ai]" << ' \n ' ;
131136 std::cout << " address : address of the target register: [0-" << MAX_MODBUS_REGS - 1 << " ]" << ' \n ' ;
132- std::cout << " The actual maximum register depends on the size of the modbus shared memory."
137+ std::cout << " The actual maximum register depends on the size of the Modbus shared memory."
133138 << ' \n ' ;
134139 std::cout << " value : value that is written to the target register" << ' \n ' ;
135140 std::cout << " Some string constants are available. The input format depends on the type of "
@@ -364,25 +369,25 @@ int main(int argc, char **argv) {
364369
365370 // check shared mem
366371 if (shm_do->get_size () > MAX_MODBUS_REGS) {
367- std::cerr << " shared memory '" << shm_do->get_name () << " is to large to be a valid modbus shared memory."
372+ std::cerr << " shared memory '" << shm_do->get_name () << " is to large to be a valid Modbus shared memory."
368373 << ' \n ' ;
369374 return EX_SOFTWARE;
370375 }
371376
372377 if (shm_di->get_size () > MAX_MODBUS_REGS) {
373- std::cerr << " shared memory '" << shm_di->get_name () << " ' is to large to be a valid modbus shared memory."
378+ std::cerr << " shared memory '" << shm_di->get_name () << " ' is to large to be a valid Modbus shared memory."
374379 << ' \n ' ;
375380 return EX_SOFTWARE;
376381 }
377382
378383 if (shm_ao->get_size () / 2 > MAX_MODBUS_REGS) {
379- std::cerr << " shared memory '" << shm_ao->get_name () << " ' is to large to be a valid modbus shared memory."
384+ std::cerr << " shared memory '" << shm_ao->get_name () << " ' is to large to be a valid Modbus shared memory."
380385 << ' \n ' ;
381386 return EX_SOFTWARE;
382387 }
383388
384389 if (shm_ai->get_size () / 2 > MAX_MODBUS_REGS) {
385- std::cerr << " shared memory '" << shm_ai->get_name () << " ' is to large to be a valid modbus shared memory."
390+ std::cerr << " shared memory '" << shm_ai->get_name () << " ' is to large to be a valid Modbus shared memory."
386391 << ' \n ' ;
387392 return EX_SOFTWARE;
388393 }
@@ -395,13 +400,13 @@ int main(int argc, char **argv) {
395400 }
396401
397402 if (shm_ao->get_size () % 2 ) {
398- std::cerr << " the size of shared memory '" << shm_ao->get_name () << " ' is odd. It is not a valid modbus shm."
403+ std::cerr << " the size of shared memory '" << shm_ao->get_name () << " ' is odd. It is not a valid Modbus shm."
399404 << ' \n ' ;
400405 return EX_SOFTWARE;
401406 }
402407
403408 if (shm_ai->get_size () % 2 ) {
404- std::cerr << " the size of shared memory '" << shm_ai->get_name () << " ' is odd. It is not a valid modbus shm."
409+ std::cerr << " the size of shared memory '" << shm_ai->get_name () << " ' is odd. It is not a valid Modbus shm."
405410 << ' \n ' ;
406411 return EX_SOFTWARE;
407412 }
@@ -425,6 +430,12 @@ int main(int argc, char **argv) {
425430 std::cerr << e.what () << ' \n ' ;
426431 return EX_SOFTWARE;
427432 }
433+ } else {
434+ std::cerr << " WARNING: No semaphore specified.\n "
435+ " Concurrent access to the shared memory is possible.\n "
436+ " This can result in CORRUPTED DATA.\n "
437+ " Use --semaphore to specify a semaphore that is provided by the Modbus client.\n " ;
438+ std::cerr << std::flush;
428439 }
429440
430441 const double SEMAPHORE_TIMEOUT_S = args[" semaphore-timeout" ].as <double >();
@@ -439,6 +450,22 @@ int main(int argc, char **argv) {
439450 static_cast <suseconds_t >(std::modf (SEMAPHORE_TIMEOUT_S, &modf_dummy) * 1'000'000 ),
440451 };
441452
453+ // modbus client pid
454+ pid_t mb_client_pid = 0 ;
455+ bool use_mb_client_pid = false ;
456+ if (args.count (" pid" )) {
457+ mb_client_pid = args[" pid" ].as <pid_t >();
458+ use_mb_client_pid = true ;
459+ } else {
460+ std::cerr << " WARNING: No Modbus client pid provided.\n "
461+ " Terminating the Modbus client application WILL NOT result in the termination of this "
462+ " application.\n "
463+ " This application WILL NOT connect to the shared memory of a restarted Modbus client.\n "
464+ " Use --pid to specify the pid of the Modbus client.\n "
465+ " Command line example: --pid $(pidof modbus-tcp-client-shm)\n "
466+ << std::flush;
467+ }
468+
442469 std::cout << std::fixed;
443470
444471 auto last_time = std::chrono::steady_clock::now ();
@@ -648,6 +675,20 @@ int main(int argc, char **argv) {
648675 input_thread.detach ();
649676
650677 while (!terminate) {
678+ if (use_mb_client_pid) {
679+ // check if modbus client is still alive
680+ int tmp = kill (mb_client_pid, 0 );
681+ if (tmp == -1 ) {
682+ if (errno == ESRCH) {
683+ std::cerr << " Modbus client (pid=" << mb_client_pid << " ) no longer alive.\n " << std::flush;
684+ } else {
685+ perror (" failed to send signal to the Modbus client" );
686+ }
687+ terminate = true ;
688+ break ;
689+ }
690+ }
691+
651692 std::this_thread::sleep_for (std::chrono::milliseconds (100 )); // NOLINT
652693 }
653694
0 commit comments