AceTimer:ScheduleTimer() leaks memory #289


  • New
  • Defect
Closed
  • _ForgeUser405586 created this issue Mar 29, 2012

    What steps will reproduce the problem?

    1. Run an addon that schedules many one-shot AceTimers and does not cancel them

    2. Watch the memory utilization of Ace3 grow slowly but without bound. After several hours I've seen the memory leak exceed 50MB.

    What version of the product are you using? Current build

    Please provide any additional information below.

    AceTimer is internally keeping a table of all the timers ever created, which is not automatically reaped. Specifically, every call to :ScheduleTimer() adds an entry to AceTimer.selfs[addon], and these entries are never removed unless you cancel them. You can see this yourself by periodically running this line of code with any addon that frequently schedules one-shot timers:

    /run local addon = ...; local n = 0; for _ in pairs(LibStub("AceTimer-3.0").selfs[addon]) do n = n + 1 end; print(n)

    This bug may just be an API documentation issue, because the handles returned by :ScheduleTimer() in the current implementation remain live until cancellation, even after they fire. The current docs for :CancelTimer():

    "Both one-shot and repeating timers can be canceled with this function, as long as the `handle` is valid and the timer has not fired yet or was canceled before."

    From this it sounds like CancelTimer is only legal if you want to stop a currently-running timer and prevent it from firing, not as a necessary destructor method the addon must call after firing to prevent library memory leakage.

    However based on comments in the library code I suspect this is really just a bug: (from AceTimer:OnUpdate())

    				local delay = timer.delay	-- NOW make a local copy, can't do it earlier in case the timer cancelled itself in the callback
    				
    				if not delay then
    					-- single-shot timer (or cancelled)
    					AceTimer.selfs[timer.object][tostring(timer)] = nil
    					timerCache = timer
    				else
    					-- repeating timer
    

    The comment "single-shot timer (or cancelled)" is wrong - timer.delay is currently ONLY nilled for timers which have been cancelled by the client, not single-shot timers who have fired.

    I suspect the correct fix is nil the delay field for single-shot timers immediately after they fire (right before the code above), so they are immediately reaped.

  • _ForgeUser405586 added the tags New Defect Mar 29, 2012
  • Forge_User_96189362 posted a comment Mar 29, 2012

    Line 239 in function Reg()

    	timer.delay = (repeating and delay)
    

    timer.delay is false for single shot timers.


    Edited Mar 29, 2012
  • Forge_User_96189362 unassigned issue from kaelten Mar 29, 2012
  • Forge_User_96189362 self-assigned this issue Mar 29, 2012

To post a comment, please login or register a new account.