LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

DiscardAsyncTimer returning before timer callback is complete

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:

  1. Am I understanding the documentation correctly?
  2. Am I doing something stupid in this example?
  3. How am I supposed to verify that my async timer threads have completed running before freeing the memory?

 

#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;
}

 

0 Kudos
Message 1 of 4
(2,834 Views)

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...

0 Kudos
Message 2 of 4
(2,753 Views)

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.

0 Kudos
Message 3 of 4
(2,644 Views)

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.

0 Kudos
Message 4 of 4
(2,638 Views)