mirror of
				https://github.com/vim/vim.git
				synced 2025-10-30 09:47:20 -04:00 
			
		
		
		
	patch 9.1.0159: Crash in WinClosed after BufUnload closes other windows
Problem: Crash in WinClosed after BufUnload closes other windows Solution: Don't trigger WinClosed if the buffer is NULL (zeertzjq) Now win_close_othertab() doesn't trigger any autocommands if the buffer is NULL, so remove the autocmd blocking above (which was added not long ago in patch v9.0.0550) for consistency. Also remove an unreachable close_last_window_tabpage() above: - It is only reached if only_one_window() returns TRUE and last_window() returns FALSE. - If only_one_window() returns TRUE, there is only one tabpage. - If there is only one tabpage and last_window() returns FALSE, the one_window() in last_window() must return FALSE, and the ONE_WINDOW in close_last_window_tabpage() must also be FALSE. - So close_last_window_tabpage() doesn't do anything and returns FALSE. Then the curtab != prev_curtab check also doesn't make much sense, and the only_one_window() can be replaced with a check for popup and a call to last_window() since this is a stricter check than only_one_window(). closes: #14166 Signed-off-by: zeertzjq <zeertzjq@outlook.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
		
				
					committed by
					
						 Christian Brabandt
						Christian Brabandt
					
				
			
			
				
	
			
			
			
						parent
						
							8a01744c56
						
					
				
				
					commit
					b2ec0da080
				
			| @@ -819,6 +819,27 @@ func Test_WinClosed_switch_tab() | ||||
|   %bwipe! | ||||
| endfunc | ||||
|  | ||||
| " This used to trigger WinClosed twice for the same window, and the window's | ||||
| " buffer was NULL in the second autocommand. | ||||
| func Test_WinClosed_BufUnload_close_other() | ||||
|   tabnew | ||||
|   let g:tab = tabpagenr() | ||||
|   let g:buf = bufnr() | ||||
|   new | ||||
|   setlocal bufhidden=wipe | ||||
|   augroup test-WinClosed | ||||
|     autocmd BufUnload * ++once exe g:buf .. 'bwipe!' | ||||
|     autocmd WinClosed * call tabpagebuflist(g:tab) | ||||
|   augroup END | ||||
|   close | ||||
|  | ||||
|   unlet g:tab | ||||
|   unlet g:buf | ||||
|   autocmd! test-WinClosed | ||||
|   augroup! test-WinClosed | ||||
|   %bwipe! | ||||
| endfunc | ||||
|  | ||||
| func s:AddAnAutocmd() | ||||
|   augroup vimBarTest | ||||
|     au BufReadCmd * echo 'hello' | ||||
|   | ||||
| @@ -704,6 +704,8 @@ static char *(features[]) = | ||||
|  | ||||
| static int included_patches[] = | ||||
| {   /* Add new patch number below this line */ | ||||
| /**/ | ||||
|     159, | ||||
| /**/ | ||||
|     158, | ||||
| /**/ | ||||
|   | ||||
							
								
								
									
										28
									
								
								src/window.c
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								src/window.c
									
									
									
									
									
								
							| @@ -2585,7 +2585,7 @@ one_window(void) | ||||
|  | ||||
| /* | ||||
|  * Close the possibly last window in a tab page. | ||||
|  * Returns TRUE when the window was closed already. | ||||
|  * Return FALSE if there are other windows and nothing is done, TRUE otherwise. | ||||
|  */ | ||||
|     static int | ||||
| close_last_window_tabpage( | ||||
| @@ -2723,7 +2723,7 @@ win_close(win_T *win, int free_buf) | ||||
|     // and then close the window and the tab page to avoid that curwin and | ||||
|     // curtab are invalid while we are freeing memory. | ||||
|     if (close_last_window_tabpage(win, free_buf, prev_curtab)) | ||||
|       return FAIL; | ||||
| 	return FAIL; | ||||
|  | ||||
|     // When closing the help window, try restoring a snapshot after closing | ||||
|     // the window.  Otherwise clear the snapshot, it's now invalid. | ||||
| @@ -2796,9 +2796,11 @@ win_close(win_T *win, int free_buf) | ||||
|  | ||||
|     win_close_buffer(win, free_buf ? DOBUF_UNLOAD : 0, TRUE); | ||||
|  | ||||
|     if (only_one_window() && win_valid(win) && win->w_buffer == NULL | ||||
| 	    && (last_window() || curtab != prev_curtab | ||||
| 		|| close_last_window_tabpage(win, free_buf, prev_curtab))) | ||||
|     if (win_valid(win) && win->w_buffer == NULL | ||||
| #if defined(FEAT_PROP_POPUP) | ||||
| 	    && !popup_is_popup(win) | ||||
| #endif | ||||
| 	    && last_window()) | ||||
|     { | ||||
| 	// Autocommands have closed all windows, quit now.  Restore | ||||
| 	// curwin->w_buffer, otherwise writing viminfo may fail. | ||||
| @@ -2812,10 +2814,7 @@ win_close(win_T *win, int free_buf) | ||||
| 						      && win->w_buffer == NULL) | ||||
|     { | ||||
| 	// Need to close the window anyway, since the buffer is NULL. | ||||
| 	// Don't trigger autocmds with a NULL buffer. | ||||
| 	block_autocmds(); | ||||
| 	win_close_othertab(win, FALSE, prev_curtab); | ||||
| 	unblock_autocmds(); | ||||
| 	return FAIL; | ||||
|     } | ||||
|  | ||||
| @@ -3352,10 +3351,15 @@ win_close_othertab(win_T *win, int free_buf, tabpage_T *tp) | ||||
| 	return; // window is already being closed | ||||
|  | ||||
|     // Trigger WinClosed just before starting to free window-related resources. | ||||
|     trigger_winclosed(win); | ||||
|     // autocmd may have freed the window already. | ||||
|     if (!win_valid_any_tab(win)) | ||||
| 	return; | ||||
|     // If the buffer is NULL, it isn't safe to trigger autocommands, | ||||
|     // and win_close() should have already triggered WinClosed. | ||||
|     if (win->w_buffer != NULL) | ||||
|     { | ||||
| 	trigger_winclosed(win); | ||||
| 	// autocmd may have freed the window already. | ||||
| 	if (!win_valid_any_tab(win)) | ||||
| 	    return; | ||||
|     } | ||||
|  | ||||
|     if (win->w_buffer != NULL) | ||||
| 	// Close the link to the buffer. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user