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(). I expected the memory to no longer be in use, but apparently this is not the case? I have an example program below that recreates my problem. When run, this program generates 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:
Example program:
#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;
}
I also asked this question on the LabWindows/CVI forum a week ago without any response: https://forums.ni.com/t5/LabWindows-CVI/DiscardAsyncTimer-returning-before-timer-callback-is-complete/td-p/3943460
I hadn't seen your question on the NI forum. The quick answer is that async timers run in a separate thread, so you need to take the usual precautions. When the error occur you can see that with [Windows][Threads] and jump from one thread to the other. Use a volatile variable for synchronisation, or better a semaphore.