English Amiga Board


Go Back   English Amiga Board > Coders > Coders. Language > Coders. C/C++

 
 
Thread Tools
Old 19 January 2021, 18:17   #1
leemmcc
Registered User

 
Join Date: Nov 2020
Location: Barnsley
Posts: 8
Timer.device memory leak?

Hi everyone,

I'm trying to write a simple piece of code to use timer.device to run a task every second.

It seems to work ok (I get Signal recieved in the shell window) but when I ctrl+c to end the program it locks, resets and gurus. Clearly there's a leak somewhere but I can't track it down.

Code:
#include <devices/timer.h>
#include <proto/dos.h>
#include <proto/exec.h>

#define TIME_SECONDS 1
#define TIME_MICROSECONDS 0

BOOL timerDeviceOpen = FALSE;
LONG timerSig;
BOOL timerRunning = FALSE;
struct timerequest *timeReq;
struct MsgPort *timerPort;

/**
 * @brief Dealloc and cleanup timer
 */
void clearTimer()
{
    if (timerDeviceOpen == TRUE){ Printf("Close timer device\n"); CloseDevice(&timeReq->tr_node); }
    if (timeReq != NULL){ Printf("Delete timerrequest\n"); DeleteExtIO((struct IORequest*)(timeReq)); }
    if (timerPort != NULL){ Printf("Delete message port\n"); DeleteMsgPort(timerPort); }
}

/**
 * @brief Start next tick of timer
 */
void tickTimer(){
	timeReq->tr_node.io_Command = TR_ADDREQUEST;
	timeReq->tr_time.tv_secs = TIME_SECONDS;
	timeReq->tr_time.tv_micro = TIME_MICROSECONDS;
	SendIO(&timeReq->tr_node);
}

int main()
{
	timerPort = CreateMsgPort();

	if (timerPort)
	{
		timeReq = (struct timerequest*)(CreateExtIO(timerPort, sizeof(struct timerequest)));

		if (OpenDevice("timer.device", UNIT_VBLANK, &timeReq->tr_node, 0) == 0)
		{
			Printf("Starting!\n");
			
			timerDeviceOpen = TRUE;

			tickTimer();

			timerRunning = TRUE;

			while (timerRunning) 
			{
				/**
				 * Wait for a signal from either ctrl+c or the timer
				 */
				ULONG sig = Wait(SIGBREAKF_CTRL_C | 1L<<timerPort->mp_SigBit);

				/**
				 * Signal from the timer
				 */
				if (timerPort && GetMsg(timerPort))
                {
					Printf ("Signal recieved\n");

					tickTimer();
                }

				/**
				 * Quit the app
				 */
				if (sig & SIGBREAKF_CTRL_C)
				{
					Printf("Ctrl-C received; timer stopping.\n");
                    timerRunning = FALSE;
				}
			}
		}
		else
		{
			Printf("Could not open timer.device!\n");
		}
		
	} 
	else 
	{
		Printf("Could not create Msg Port!\n");
	}

	/**
	 * Dealloc and clean
	 */
	clearTimer();
	Printf("Done!\n");

	return 0;
}
leemmcc is offline  
Old 19 January 2021, 19:10   #2
meynaf
son of 68k
meynaf's Avatar
 
Join Date: Nov 2007
Location: Lyon / France
Age: 48
Posts: 4,142
A memory leak wouldn't crash, it would just not free all memory.
Here you have called SendIO but what you've sent isn't cancelled upon exit. Perhaps some call to AbortIO is needed.
meynaf is online now  
Old 19 January 2021, 19:15   #3
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 45
Posts: 24,625
Pending timer requests must be canceled first. For example AbortIO() + WaitIO() does it.
Toni Wilen is offline  
Old 19 January 2021, 21:38   #4
Thomas Richter
Registered User
 
Join Date: Jan 2019
Location: Germany
Posts: 962
GetMsg() is not exactly the right way to handle IO request. You send out the request with SendIO(). You test whether the request is done with CheckIO(), which returns the request when done, or NULL if it is not. CheckIO() does *not* remove the request. Use WaitIO() for that. It waits for the request, then returns when its done, and removes the request from the port, ready to re-use it. WaitIO() does of course not block if the request is already done. To abort a request, use AbortIO(), then WaitIO().
Thomas Richter is offline  
Old 19 January 2021, 22:27   #5
leemmcc
Registered User

 
Join Date: Nov 2020
Location: Barnsley
Posts: 8
OK, that makes sense. So basically because I'm not using a combination of WaitIO(), AbortIO() and CheckIO() I have no way of telling whether the request is fully complete before I starting a new request. And, in addition to that, I'm not checking the state of the request before exit.

Thanks for your help everyone.

Last edited by leemmcc; 19 January 2021 at 23:19.
leemmcc is offline  
Old 19 January 2021, 23:51   #6
thomas
Registered User
thomas's Avatar
 
Join Date: Jan 2002
Location: Germany
Posts: 6,183
You do it like this:

Code:
			ULONG timersig = 1L<<timerPort->mp_SigBit;
			ULONG sig = Wait(SIGBREAKF_CTRL_C | timersig);

			/**
			 * Signal from the timer
			 */
			if (sig & timersig)
			{
				Printf ("Signal recieved\n");
				WaitIO (timeReq);
				tickTimer();
			}

			/**
			 * Quit the app
			 */
			if (sig & SIGBREAKF_CTRL_C)
			{
				Printf("Ctrl-C received; timer stopping.\n");
				timerRunning = FALSE;
			}

At the end, just after the while(){} loop you call AbortIO and WaitIO.

Be warned that you must not call AbortIO if the timerequest was never used before. As you call tickTimer just before the loop, put the AbortIO immediately after the loop. Do not move it before or into clearTimer, although this looks like a logical place. (You can safely call AbortIO/WaitIO if the request already ended. No need to call CheckIO.)
thomas is offline  
Old 01 February 2021, 16:25   #7
tygre
Returning fan!

tygre's Avatar
 
Join Date: Jan 2011
Location: Montréal, QC, Canada
Posts: 850
Hi Leemmcc and all!

For AmigaMapPing, I also had to play with timer so I created a simple implementation with three functions:
  • struct timerequest *timer_create(void); to initialise the timer.
  • int timer_start(struct timerequest *timereq, int minutes); that starts a timer for minutes.
  • BOOL timer_done(struct timerequest *timereq); to check if any signal received from the timer is for our timerequest.
  • void timer_free (struct timerequest *timereq); to free/close everything once done with the timer.

It should be reusable "as is" in any project. You can find it here: its API and its implementation and an example. Hope that it can help!

Cheers!

Last edited by tygre; 01 February 2021 at 16:25. Reason: Typos
tygre is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
Memory Leak Tracing Help Warty Coders. C/C++ 14 19 February 2021 12:14
timer.device:GetSysTime:UNIT_VBLANK not recognized VladR Coders. Asm / Hardware 8 26 April 2020 13:44
[blitz] timer device + window IDCMP_INTUITICS = trouble peceha Coders. Blitz Basic 6 20 October 2019 23:02
Clipboard memory leak Leandro Jardim support.WinUAE 2 21 February 2012 22:48
Using timer.device in C (VBCC) DBAlex Coders. General 2 28 June 2011 23:10

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 16:10.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2021, vBulletin Solutions Inc.
Page generated in 0.09587 seconds with 13 queries