diff -r 5d8a4deacfe1 -r da8de4ef0449 modbus/mb_runtime.c --- a/modbus/mb_runtime.c Tue Jun 23 13:50:21 2020 +0200 +++ b/modbus/mb_runtime.c Wed Jun 24 14:38:11 2020 +0200 @@ -295,24 +295,10 @@ static void *__mb_client_thread(void *_index) { int client_node_id = (char *)_index - (char *)NULL; // Use pointer arithmetic (more portable than cast) - struct timespec next_cycle; - int period_sec = client_nodes[client_node_id].comm_period / 1000; /* comm_period is in ms */ - int period_nsec = (client_nodes[client_node_id].comm_period %%1000)*1000000; /* comm_period is in ms */ // Enable thread cancelation. Enabled is default, but set it anyway to be safe. pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); - // configure the timer for periodic activation - { - struct itimerspec timerspec; - timerspec.it_interval.tv_sec = period_sec; - timerspec.it_interval.tv_nsec = period_nsec; - timerspec.it_value = timerspec.it_interval; - - if (timer_settime(client_nodes[client_node_id].timer_id, 0 /* flags */, &timerspec, NULL) < 0) - fprintf(stderr, "Modbus plugin: Error configuring periodic activation timer for Modbus client %%s.\n", client_nodes[client_node_id].location); - } - /* loop the communication with the client * * When the client thread has difficulty communicating with remote client and/or server (network issues, for example), @@ -492,7 +478,10 @@ static int stop_mb_client_timer_thread; static void *__mb_client_timer_thread(void *_index) { sigset_t set; - int signum = SIGALRM; + int signum; + sigemptyset(&set); + sigaddset(&set, SIGALRM); + int client_node_id = (char *)_index - (char *)NULL; // Use pointer arithmetic (more portable than cast) printf("%%d\n", client_node_id); /* initialize the timer that will be used to periodically activate the client node */ @@ -500,24 +489,39 @@ // start off by reseting the flag that will be set whenever the timer expires client_nodes[client_node_id].periodic_act = 0; - struct sigevent evp = {0}; - evp.sigev_notify = SIGEV_THREAD_ID; /* Notification method - call a function in a new thread context */ - evp.sigev_signo = SIGALRM; - evp.sigev_value.sival_int = client_node_id; /* Data passed to function upon notification - used to indentify which client node to activate */ - - if (timer_create(CLOCK_MONOTONIC, &evp, &(client_nodes[client_node_id].timer_id)) < 0) { + if (timer_create(CLOCK_REALTIME, NULL, &(client_nodes[client_node_id].timer_id)) < 0) { fprintf(stderr, "Modbus plugin: Error (%%s) creating timer for modbus client node %%s\n", strerror(errno), client_nodes[client_node_id].location); return NULL; } } + int period_sec = client_nodes[client_node_id].comm_period / 1000; /* comm_period is in ms */ + int period_nsec = (client_nodes[client_node_id].comm_period %%1000)*1000000; /* comm_period is in ms */ + + // configure the timer for periodic activation + { + struct itimerspec timerspec; + timerspec.it_interval.tv_sec = period_sec; + timerspec.it_interval.tv_nsec = period_nsec; + timerspec.it_value = timerspec.it_interval; + + if (timer_settime(client_nodes[client_node_id].timer_id, 0 /* flags */, &timerspec, NULL) < 0) + fprintf(stderr, "Modbus plugin: Error configuring periodic activation timer for Modbus client %%s.\n", client_nodes[client_node_id].location); + } + stop_mb_client_timer_thread = 0; while(!stop_mb_client_timer_thread) { if(sigwait (&set, &signum) == -1) perror ("sigwait"); + if(stop_mb_client_timer_thread) break; - __client_node_timer_callback_function(client_node_id); + + if(signum == SIGALRM) + __client_node_timer_callback_function(client_node_id); + else + fprintf(stderr, "Modbus plugin: spurious wakeup of timer thread for Modbus client %%s.\n", client_nodes[client_node_id].location); + } // timer was created, so we try to destroy it! @@ -791,8 +795,6 @@ if (client_nodes[index].init_state >= 4) { stop_mb_client_timer_thread = 1; pthread_kill(client_nodes[index].timer_thread_id, SIGALRM); - // thread was launched, so we try to cancel it! - close = pthread_cancel(client_nodes[index].timer_thread_id); close |= pthread_join (client_nodes[index].timer_thread_id, NULL); if (close < 0) fprintf(stderr, "Modbus plugin: Error closing timer thread for modbus client node %%s\n", client_nodes[index].location);