]> granicus.if.org Git - vim/commitdiff
patch 9.0.0361: removing a listener may result in a memory leak v9.0.0361
authorYegappan Lakshmanan <yegappan@yahoo.com>
Fri, 2 Sep 2022 16:12:07 +0000 (17:12 +0100)
committerBram Moolenaar <Bram@vim.org>
Fri, 2 Sep 2022 16:12:07 +0000 (17:12 +0100)
Problem:    Removing a listener may result in a memory leak and remove
            subsequent listerns.
Solution:   Init the "prev" pointer only once. (Yegappan Lakshmanan,
            closes #11039)

src/change.c
src/testdir/test_listener.vim
src/version.c

index 71ad9eaf87ef6ebf44294fa5ce5291601fbaafb8..b84dfad358cb21c61ff83576bd7ded6e213e8a2a 100644 (file)
@@ -362,6 +362,7 @@ invoke_listeners(buf_T *buf)
     int                save_updating_screen = updating_screen;
     static int recursive = FALSE;
     listener_T *next;
+    listener_T *prev;
 
     if (buf->b_recorded_changes == NULL  // nothing changed
            || buf->b_listener == NULL   // no listeners
@@ -406,10 +407,9 @@ invoke_listeners(buf_T *buf)
     }
 
     // If f_listener_remove() was called may have to remove a listener now.
+    prev = NULL;
     for (lnr = buf->b_listener; lnr != NULL; lnr = next)
     {
-       listener_T      *prev = NULL;
-
        next = lnr->lr_next;
        if (lnr->lr_id == 0)
            remove_listener(buf, lnr, prev);
index 82b5ff03c9cfd002838fb58bbb2f2d20c4f36ad0..413275d464c6d1e77c22638bd7dbe748b706c6c5 100644 (file)
@@ -387,6 +387,37 @@ func Test_remove_listener_in_callback()
   unlet g:listener_called
 endfunc
 
+" When multiple listeners are registered, remove one listener and verify the
+" other listener is still called
+func Test_remove_one_listener_in_callback()
+  new
+  let g:listener1_called = 0
+  let g:listener2_called = 0
+  let s:ID1 = listener_add('Listener1')
+  let s:ID2 = listener_add('Listener2')
+  func Listener1(...)
+    call listener_remove(s:ID1)
+    let g:listener1_called += 1
+  endfunc
+  func Listener2(...)
+    let g:listener2_called += 1
+  endfunc
+  call setline(1, ['foo'])
+  call feedkeys("~", 'xt')
+  call listener_flush()
+  call feedkeys("~", 'xt')
+  call listener_flush()
+  call assert_equal(1, g:listener1_called)
+  call assert_equal(2, g:listener2_called)
+
+  call listener_remove(s:ID2)
+  bwipe!
+  delfunc Listener1
+  delfunc Listener2
+  unlet g:listener1_called
+  unlet g:listener2_called
+endfunc
+
 func Test_no_change_for_empty_undo()
   new
   let text = ['some word here', 'second line']
index 4f2b3dcf15a41dda62e3ef6b68683caa84a2beef..c6d3869db81f3b1f3b80074f8499213b77c52251 100644 (file)
@@ -707,6 +707,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    361,
 /**/
     360,
 /**/