To: vim_dev@googlegroups.com Subject: Patch 8.2.3426 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.3426 Problem: Crash when deleting a listener in a listener callback. (Naohiro Ono) Solution: Mark the listener and delete it later. (closes #8863) Files: src/change.c, src/testdir/test_listener.vim *** ../vim-8.2.3425/src/change.c 2021-07-27 22:00:39.737712414 +0200 --- src/change.c 2021-09-11 15:05:53.812528529 +0200 *************** *** 293,298 **** --- 293,310 ---- invoke_listeners(buf); } + + static void + remove_listener(buf_T *buf, listener_T *lnr, listener_T *prev) + { + if (prev != NULL) + prev->lr_next = lnr->lr_next; + else + buf->b_listener = lnr->lr_next; + free_callback(&lnr->lr_callback); + vim_free(lnr); + } + /* * listener_remove() function */ *************** *** 317,328 **** next = lnr->lr_next; if (lnr->lr_id == id) { ! if (prev != NULL) ! prev->lr_next = lnr->lr_next; ! else ! buf->b_listener = lnr->lr_next; ! free_callback(&lnr->lr_callback); ! vim_free(lnr); rettv->vval.v_number = 1; return; } --- 329,341 ---- next = lnr->lr_next; if (lnr->lr_id == id) { ! if (textwinlock > 0) ! { ! // in invoke_listeners(), clear ID and delete later ! lnr->lr_id = 0; ! return; ! } ! remove_listener(buf, lnr, prev); rettv->vval.v_number = 1; return; } *************** *** 357,362 **** --- 370,376 ---- linenr_T added = 0; int save_updating_screen = updating_screen; static int recursive = FALSE; + listener_T *next; if (buf->b_recorded_changes == NULL // nothing changed || buf->b_listener == NULL // no listeners *************** *** 400,405 **** --- 414,431 ---- clear_tv(&rettv); } + // If f_listener_remove() was called may have to remove a listener now. + 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); + else + prev = lnr; + } + --textwinlock; list_unref(buf->b_recorded_changes); buf->b_recorded_changes = NULL; *** ../vim-8.2.3425/src/testdir/test_listener.vim 2020-08-12 18:50:31.879655802 +0200 --- src/testdir/test_listener.vim 2021-09-11 15:05:16.116570551 +0200 *************** *** 370,373 **** --- 370,391 ---- delfunc Listener endfunc + func Test_remove_listener_in_callback() + new + let s:ID = listener_add('Listener') + func Listener(...) + call listener_remove(s:ID) + let g:listener_called = 'yes' + endfunc + call setline(1, ['foo']) + call feedkeys("lD", 'xt') + call listener_flush() + call assert_equal('yes', g:listener_called) + + bwipe! + delfunc Listener + unlet g:listener_called + endfunc + + " vim: shiftwidth=2 sts=2 expandtab *** ../vim-8.2.3425/src/version.c 2021-09-11 12:15:02.875927707 +0200 --- src/version.c 2021-09-11 14:55:22.649016304 +0200 *************** *** 757,758 **** --- 757,760 ---- { /* Add new patch number below this line */ + /**/ + 3426, /**/ -- hundred-and-one symptoms of being an internet addict: 26. You check your mail. It says "no new messages." So you check it again. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///