Skip to content
  • Praveenkumar.Hulakund's avatar
    e6f47a0e
    Bug#20705648 - max_statement_time leaks memory on windows · e6f47a0e
    Praveenkumar.Hulakund authored
    Bug#20705642 - max_statement_time: assertion failed: pending || thd_timer->thread_id
    
    Description:
    -------------
    Both of these issues are related to deletion of timer from the
    Timer-queue.
    
    Issue in bug20705648 is, the timer object created in windows is
    not deleted after the timer expiration. Hence memory leak is seen
    on the windows.
    
    Issue in bug20705642 is, the timer reset operation sets state of
    timer as "not expired" when the timer is already expired and the
    callback function execution of it is completed. This is resulting
    in the assert condition failure.
    
    Analysis:
    -------------
    In the current code, for the set timer operation new Timer-queue
    timer is created. For timer cancel and destroy operations, timer
    -queue timer is deleted from the Timer-queue. But when timer is
    expired, assumption was timers of type "WT_EXECUTEONLYONCE" are
    deleted. But these timer objects are not delete from Timer-queue
    on expiration. Hence the memory leak is observed in the current
    code.
    
    The windows API to delete timer-queue timer,
    
        1 Fails when timer is expired or callback function is in
          execution.
    
        2 Succeeds when timer is *not* expired.
    
        3 Succeeds when timer is expired and callback function
          execution is completed.
    
    In the current code, case 1 and 2 are handled properly but
    case 3 is not handled. Because of which windows timer reset operation
    returns timer state as not expired. If timer is not expired then
    non zero thread_id value is expected (as notify function for timer
    expiration is not called) in reset timer code. Assert condition to
    check the same fails in debug build because of not handling
    condition 3. In non-debug build, timer object is just set for the
    reuse.
    
    Fix:
    ------
    To fix memory leak, if timer is expired then deleting it from the
    queue on next timer set or timer destroy operations.
    
    To fix assert issues, new timer_state member is introduced in the
    my_timer for windows.
    
    timer_state is set to "TIMER_SET" in timer set operation and
    in timer_callback  to "TIMER_EXPIRED".
    
    With timer_state, setting timer expired/not expired state in
    timer reset operation is handled as below,
    
    Timer reset operation (my_timer_cancel()):
      Windows API DeleteTimerQueueTimer is used to delete m
      the timer queue. This API,
    
      * Succeeds when timer is *not* expired.
          state is set to *not expired* as timer_state is TIMER_SET.
    
      * Succeeds when timer is expired and callback function
        execution is completed.
          state is set to *expired* as timer_state is TIMER_EXPIRED.
    
      *  *Fails* when timer is expired or callback function is in
         execution.
           state is set to *expired*.
           timer_state value is *not* checked in this case.
    
    So to fix assert condition failure, "timer_state" value is
    checked to set timer expired or non expired state. Now if
    timer cancellation is called after timer callback execution
    then "expired" state is returned.
    
    Testing:
    --------
    Without patch, memory leak of around 400kb/sec is observed with
    mysqlslap.exe -hlocalhost --number-of-queries=10000000000 --query="select
    max_statement_time=1 sleep(rand()) ;" --iterations=1000000
    --create-schema=test
    
    With patch no memory leak or crash is observed,
    \bin>time
    The current time is: 11:21:03.07
    Enter the new time:
    
    \bin>tasklist /FI "IMAGENAME eq mysqld.exe"
    
    Image Name                     PID Session Name        Session#    Mem Usage
    ========================= ======== ================ =========== ============
    mysqld.exe                   11304 RDP-Tcp#28                 2    119,244 K
    
    \bin>time
    The current time is: 11:28:35.59
    Enter the new time: .
    
    \bin>tasklist /FI "IMAGENAME eq mysqld.exe"
    
    Image Name                     PID Session Name        Session#    Mem Usage
    ========================= ======== ================ =========== ============
    mysqld.exe                   11304 RDP-Tcp#28                 2    119,244 K
    e6f47a0e
    Bug#20705648 - max_statement_time leaks memory on windows
    Praveenkumar.Hulakund authored
    Bug#20705642 - max_statement_time: assertion failed: pending || thd_timer->thread_id
    
    Description:
    -------------
    Both of these issues are related to deletion of timer from the
    Timer-queue.
    
    Issue in bug20705648 is, the timer object created in windows is
    not deleted after the timer expiration. Hence memory leak is seen
    on the windows.
    
    Issue in bug20705642 is, the timer reset operation sets state of
    timer as "not expired" when the timer is already expired and the
    callback function execution of it is completed. This is resulting
    in the assert condition failure.
    
    Analysis:
    -------------
    In the current code, for the set timer operation new Timer-queue
    timer is created. For timer cancel and destroy operations, timer
    -queue timer is deleted from the Timer-queue. But when timer is
    expired, assumption was timers of type "WT_EXECUTEONLYONCE" are
    deleted. But these timer objects are not delete from Timer-queue
    on expiration. Hence the memory leak is observed in the current
    code.
    
    The windows API to delete timer-queue timer,
    
        1 Fails when timer is expired or callback function is in
          execution.
    
        2 Succeeds when timer is *not* expired.
    
        3 Succeeds when timer is expired and callback function
          execution is completed.
    
    In the current code, case 1 and 2 are handled properly but
    case 3 is not handled. Because of which windows timer reset operation
    returns timer state as not expired. If timer is not expired then
    non zero thread_id value is expected (as notify function for timer
    expiration is not called) in reset timer code. Assert condition to
    check the same fails in debug build because of not handling
    condition 3. In non-debug build, timer object is just set for the
    reuse.
    
    Fix:
    ------
    To fix memory leak, if timer is expired then deleting it from the
    queue on next timer set or timer destroy operations.
    
    To fix assert issues, new timer_state member is introduced in the
    my_timer for windows.
    
    timer_state is set to "TIMER_SET" in timer set operation and
    in timer_callback  to "TIMER_EXPIRED".
    
    With timer_state, setting timer expired/not expired state in
    timer reset operation is handled as below,
    
    Timer reset operation (my_timer_cancel()):
      Windows API DeleteTimerQueueTimer is used to delete m
      the timer queue. This API,
    
      * Succeeds when timer is *not* expired.
          state is set to *not expired* as timer_state is TIMER_SET.
    
      * Succeeds when timer is expired and callback function
        execution is completed.
          state is set to *expired* as timer_state is TIMER_EXPIRED.
    
      *  *Fails* when timer is expired or callback function is in
         execution.
           state is set to *expired*.
           timer_state value is *not* checked in this case.
    
    So to fix assert condition failure, "timer_state" value is
    checked to set timer expired or non expired state. Now if
    timer cancellation is called after timer callback execution
    then "expired" state is returned.
    
    Testing:
    --------
    Without patch, memory leak of around 400kb/sec is observed with
    mysqlslap.exe -hlocalhost --number-of-queries=10000000000 --query="select
    max_statement_time=1 sleep(rand()) ;" --iterations=1000000
    --create-schema=test
    
    With patch no memory leak or crash is observed,
    \bin>time
    The current time is: 11:21:03.07
    Enter the new time:
    
    \bin>tasklist /FI "IMAGENAME eq mysqld.exe"
    
    Image Name                     PID Session Name        Session#    Mem Usage
    ========================= ======== ================ =========== ============
    mysqld.exe                   11304 RDP-Tcp#28                 2    119,244 K
    
    \bin>time
    The current time is: 11:28:35.59
    Enter the new time: .
    
    \bin>tasklist /FI "IMAGENAME eq mysqld.exe"
    
    Image Name                     PID Session Name        Session#    Mem Usage
    ========================= ======== ================ =========== ============
    mysqld.exe                   11304 RDP-Tcp#28                 2    119,244 K
Loading