06-30-2019 11:25 AM - edited 06-30-2019 11:32 AM
I'm trying to write a program in LabWindows/CVI 2017 using async timers but ran into a problem with the DiscardAsyncTimer() function. From the documentation for DiscardAsyncTimer():
A call to create or discard an asynchronous timer will not complete (will block) until all outstanding asynchronous callbacks return.
However, I ran into some memory problems where I was freeing memory used in my async timer thread after calling DiscardAsyncTimer() thinking that the memory was no longer in use. But apparently this is not the case? I have an example program below that very easily recreates my problem: a "general protection fault" due to trying to access freed memory. However, if my understanding of the documentation, and the documentation itself, is correct, this should be impossible since DiscardAsyncTimer() is supposed to block until all callbacks return.
My questions:
#include <ansi_c.h> #include <asynctmr.h> #include <stdio.h> #include <utility.h> #include <userint.h> typedef struct { int* array; } MyStruct; int CVICALLBACK ShuffleValues (int reserved, int timerId, int event, void *callbackData, int eventData1, int eventData2) { if (event == EVENT_TIMER_TICK) { printf("start\n"); MyStruct* mystruct = callbackData; // Shuffle values for(int i = 0;i < 1000;i++) { mystruct->array[0] = mystruct->array[1]; mystruct->array[1] = mystruct->array[2]; Delay(0.01); } printf("finished\n"); } return 0; } int main () { // Allocate memory MyStruct* mystruct = malloc(sizeof(MyStruct)); mystruct->array = malloc(10 * sizeof(int)); // Start Async Timer int timer = NewAsyncTimer(0.01, -1, 1, ShuffleValues, mystruct); // Wait a while to let the timer thread run a bit Delay(0.5); // Destroy Async Timer printf("start destroying\n"); int retval = DiscardAsyncTimer(timer); printf("finished destroying: %d\n", retval); // Free memory now that the timer thread is no longer running free(mystruct->array); free(mystruct); Delay(1); return 0; }
07-07-2019 10:04 AM
Since it has been a week without any response I have also asked this question on stackoverflow: https://stackoverflow.com/questions/56923320/discardasynctimer-returning-before-timer-callback-is-co...
09-11-2019 07:22 AM
Yes, this is not the expected behavior. I simplified the code like this:
#include <ansi_c.h> #include <asynctmr.h> #include <stdio.h> #include <utility.h> #include <userint.h> int CVICALLBACK ShuffleValues (int reserved, int timerId, int event, void *callbackData, int eventData1, int eventData2) { switch (event) { case EVENT_TIMER_TICK: printf("start\n"); Delay(10); printf("finished\n"); break; case EVENT_DISCARD: printf("discard\n"); break; } return 1; } int main (void) { int timer = NewAsyncTimer(0.01, -1, 1, ShuffleValues, NULL); // Wait a while to let the timer thread run a bit Delay(0.5); printf("start destroying\n"); int retval = DiscardAsyncTimer(timer); printf("finished destroying: %d\n", retval); return 0; }
and it is clear that the timer is still running. Another strange thing is that EVENT_DISCARD is called in the main thread, not in the timer thread as one would expect. I've used async timers many times without noticing those issues.
09-11-2019 07:44 AM
Okay, that also explains something else I was seeing. That is, calling DiscardAsyncTimer() seemed to interrupt my already running timer thread for the EVENT_DISCARD event. I assumed this was just how it worked, but running in the main thread rather than the timer thread explains it.