vim-patch:9.2.{0252,0253,0254}: I want to get off b_nwindows' wild ride#38473
Merged
seandewar merged 3 commits intoneovim:masterfrom Mar 29, 2026
Merged
Conversation
94c4562 to
8df8695
Compare
Member
Author
|
Tests seem to pass. Just had to update unit tests with the new Pretty cool. I'll still probably spend more time combing over stuff because I'm paranoid. 😁 |
seandewar
added a commit
to seandewar/neovim
that referenced
this pull request
Mar 25, 2026
Problem: - Small error in port of v9.1.0678, causing :ball to check w_locked for the wrong window. - After neovim#27439, free_all_mem() may not wipe out buffers that were open in more than one window before windows were freed. Solution: - Check win_locked() for wp in ex_buffer_all(), not curwin. - Set b_nwindows to 0 in free_all_mem() before calling close_buffer(). Ref: neovim#38473 (comment) No need to block these fixes on that. free_all_mem() change also looks like it fixed the "N lua references were leaked!" warnings on the CI in that PR.
seandewar
added a commit
that referenced
this pull request
Mar 25, 2026
Problem: - Small error in port of v9.1.0678, causing :ball to check w_locked for the wrong window. - After #27439, free_all_mem() may not wipe out buffers that were open in more than one window before windows were freed. Solution: - Check win_locked() for wp in ex_buffer_all(), not curwin. - Set b_nwindows to 0 in free_all_mem() before calling close_buffer(). Ref: #38473 (comment) No need to block these fixes on that. free_all_mem() change also looks like it fixed the existing "N lua references were leaked!" warnings on the CI.
4c298ef to
640a0ff
Compare
b_nwindows' wild ride
640a0ff to
31bc432
Compare
Member
Author
|
Some remarks in the commit messages. I think it's safest to wait until after the release with these fixes, in case I screwed something up. (But I think it's solid 🙏; I'll add Also, maybe 9.2.0252 should be considered a partial patch? I 'unno. |
zeertzjq
approved these changes
Mar 27, 2026
…loaded
Problem: if close_buffer() in set_curbuf() unloads curbuf, NULL pointer
accesses may occur from enter_buffer() calling
end_visual_mode(), as curbuf is already abandoned and possibly
unloaded. Also, selection registers may not contain the
selection with clipboard+=autoselect(plus).
Solution: Move close_buffer()'s end_visual_mode() call to buf_freeall(), after
any autocmds that may restart it, but just before freeing anything
(Sean Dewar)
related: vim/vim#19728
vim/vim@a8fdfd4
Maybe this should be considered partial? clipboard+=autoselect isn't
implemented. If it is, we may need to update these comments to mention
TextYankPost being possible, and unskip its test.
Co-authored-by: Sean Dewar <6256228+seandewar@users.noreply.github.com>
…g buffers
Problem: close_buffer() callers incorrectly handle b_nwindows,
especially after nasty autocmds, allowing it to go
out-of-sync. May lead to buffers that can't be unloaded, or
buffers that are prematurely freed whilst displayed.
Solution: Modify close_buffer() and review its callers; let them
decrement b_nwindows if it didn't unload the buffer. Remove
some now unneeded workarounds like 8.2.2354, 9.1.0143,
9.1.0764, which didn't always work (Sean Dewar)
(endless yapping omitted)
related: vim/vim#19728
vim/vim@bf21df1
b_nwindows = 0 change for free_all_mem() was already ported.
Originally Nvim returned true when b_nwindows was decremented before the end was
reached (to better indicate the decrement). That's not needed anymore, so just
return true only at the end, like Vim. (retval isn't used anywhere now anyways)
Set textlock for dict watchers at the end of close_buffer() to prevent them from
switching windows, as that can leave a window with a NULL buffer. (possible
before this PR, but the new assert catches it; added a test)
Despite textlock, things still aren't ideal, as watchers may observe the buffer
as unloaded and hidden (b_nwindows was decremented), yet still in a window...
Likewise, for Nvim, wipe_qf_buffer()'s comment may not be entirely accurate;
autocmds are blocked, but on_detach callbacks (textlocked) and dict watchers may
still run. Might be problematic, but those aren't new issues.
Co-authored-by: Sean Dewar <6256228+seandewar@users.noreply.github.com>
Problem: w_locked can be bypassed when recursively set if not restored
to its prior value.
Solution: Rather than save/restore everywhere, just make it a count,
like other locks (Sean Dewar)
Requires the previous commit, otherwise b_nwindows will be wrong in
tests, which causes a bunch of weird failures.
closes: vim/vim#19728
vim/vim@7cb43f2
Co-authored-by: Sean Dewar <6256228+seandewar@users.noreply.github.com>
31bc432 to
6b0532c
Compare
zeertzjq
added a commit
to zeertzjq/neovim
that referenced
this pull request
Mar 30, 2026
The NULL checks added in neovim#35679 are no longer needed after neovim#38473. _____________________________________________________________________________________________ *** CID 645258: (REVERSE_INULL) /src/nvim/buffer.c: 645 in close_buffer() 639 // Autocommands deleted the buffer. 640 emsg(_(e_auabort)); 641 return false; 642 } 643 buf->b_locked--; 644 buf->b_locked_split--; >>> CID 645258: (REVERSE_INULL) >>> Null-checking "win" suggests that it may be null, but it has already been dereferenced on all paths leading to the check. 645 if (abort_if_last && win != NULL && one_window(win, NULL)) { 646 // Autocommands made this the only window. 647 emsg(_(e_auabort)); 648 return false; 649 } 650 } /src/nvim/buffer.c: 626 in close_buffer() 620 // Autocommands deleted the buffer. 621 emsg(_(e_auabort)); 622 return false; 623 } 624 buf->b_locked--; 625 buf->b_locked_split--; >>> CID 645258: (REVERSE_INULL) >>> Null-checking "win" suggests that it may be null, but it has already been dereferenced on all paths leading to the check. 626 if (abort_if_last && win != NULL && one_window(win, NULL)) { 627 // Autocommands made this the only window. 628 emsg(_(e_auabort)); 629 return false; 630 } 631
zeertzjq
added a commit
that referenced
this pull request
Mar 30, 2026
The NULL checks added in #35679 are no longer needed after #38473. _____________________________________________________________________________________________ *** CID 645258: (REVERSE_INULL) /src/nvim/buffer.c: 645 in close_buffer() 639 // Autocommands deleted the buffer. 640 emsg(_(e_auabort)); 641 return false; 642 } 643 buf->b_locked--; 644 buf->b_locked_split--; >>> CID 645258: (REVERSE_INULL) >>> Null-checking "win" suggests that it may be null, but it has already been dereferenced on all paths leading to the check. 645 if (abort_if_last && win != NULL && one_window(win, NULL)) { 646 // Autocommands made this the only window. 647 emsg(_(e_auabort)); 648 return false; 649 } 650 } /src/nvim/buffer.c: 626 in close_buffer() 620 // Autocommands deleted the buffer. 621 emsg(_(e_auabort)); 622 return false; 623 } 624 buf->b_locked--; 625 buf->b_locked_split--; >>> CID 645258: (REVERSE_INULL) >>> Null-checking "win" suggests that it may be null, but it has already been dereferenced on all paths leading to the check. 626 if (abort_if_last && win != NULL && one_window(win, NULL)) { 627 // Autocommands made this the only window. 628 emsg(_(e_auabort)); 629 return false; 630 } 631
MariaSolOs
pushed a commit
to MariaSolOs/neovim
that referenced
this pull request
Apr 15, 2026
The NULL checks added in neovim#35679 are no longer needed after neovim#38473. _____________________________________________________________________________________________ *** CID 645258: (REVERSE_INULL) /src/nvim/buffer.c: 645 in close_buffer() 639 // Autocommands deleted the buffer. 640 emsg(_(e_auabort)); 641 return false; 642 } 643 buf->b_locked--; 644 buf->b_locked_split--; >>> CID 645258: (REVERSE_INULL) >>> Null-checking "win" suggests that it may be null, but it has already been dereferenced on all paths leading to the check. 645 if (abort_if_last && win != NULL && one_window(win, NULL)) { 646 // Autocommands made this the only window. 647 emsg(_(e_auabort)); 648 return false; 649 } 650 } /src/nvim/buffer.c: 626 in close_buffer() 620 // Autocommands deleted the buffer. 621 emsg(_(e_auabort)); 622 return false; 623 } 624 buf->b_locked--; 625 buf->b_locked_split--; >>> CID 645258: (REVERSE_INULL) >>> Null-checking "win" suggests that it may be null, but it has already been dereferenced on all paths leading to the check. 626 if (abort_if_last && win != NULL && one_window(win, NULL)) { 627 // Autocommands made this the only window. 628 emsg(_(e_auabort)); 629 return false; 630 } 631
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ref: vim/vim#19728