# HG changeset patch # User Edouard Tisserant # Date 1676630518 -3600 # Node ID 265fc8001d0a6895cfaf44a5b5ca9c19343b4e25 # Parent 516779f11803ed3c059d085c673a44b6ace40d39 Runtime: Fix bugs in Linux target. - next occurence absolute time computation failing on 32-bit because of casting - PLC thread was started before period was set, potentially passing uninitialized timespec to clock_nanosleep() diff -r 516779f11803 -r 265fc8001d0a targets/Linux/plc_Linux_main.c --- a/targets/Linux/plc_Linux_main.c Thu Feb 16 12:13:16 2023 +0100 +++ b/targets/Linux/plc_Linux_main.c Fri Feb 17 11:41:58 2023 +0100 @@ -44,12 +44,12 @@ static void inc_timespec(struct timespec *ts, unsigned long long value_ns) { + long long next_ns = ((long long) ts->tv_sec * 1000000000) + ts->tv_nsec + value_ns; #ifdef __lldiv_t_defined - lldiv_t next_div = lldiv(ts->tv_sec * 1000000000 + ts->tv_nsec + value_ns, 1000000000); + lldiv_t next_div = lldiv(next_ns, 1000000000); ts->tv_sec = next_div.quot; ts->tv_nsec = next_div.rem; #else - long long next_ns = ts->tv_sec * 1000000000 + ts->tv_nsec + value_ns; ts->tv_sec = next_ns / 1000000000; ts->tv_nsec = next_ns % 1000000000; #endif @@ -66,7 +66,7 @@ // interrupt clock_nanpsleep pthread_kill(PLC_thread, SIGUSR1); } -// + void catch_signal(int sig) { // signal(SIGTERM, catch_signal); @@ -91,8 +91,13 @@ // Sleep until next PLC run // TODO check result of clock_nanosleep and wait again or exit eventually int res = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next_abs_time, NULL); - if(res==EINTR) continue; - if(res!=0) return; + if(res==EINTR){ + continue; + } + if(res!=0){ + printf("PLC thread died with error %d \n", res); + return; + } PLC_GetTime(&__CURRENT_TIME); __run(); inc_timespec(&next_abs_time, period_ns); @@ -107,8 +112,6 @@ PLC_shutdown = 0; - pthread_create(&PLC_thread, NULL, (void*) &PLC_thread_proc, NULL); - pthread_mutex_init(&debug_wait_mutex, NULL); pthread_mutex_init(&debug_mutex, NULL); pthread_mutex_init(&python_wait_mutex, NULL); @@ -126,7 +129,11 @@ /* install signal handler for manual break */ signal(SIGINT, catch_signal); - PLC_SetTimer(common_ticktime__,common_ticktime__); + /* initialize next occurence and period */ + period_ns = common_ticktime__; + clock_gettime(CLOCK_MONOTONIC, &next_abs_time); + + pthread_create(&PLC_thread, NULL, (void*) &PLC_thread_proc, NULL); }else{ return 1; }