comparison src/quickfix.c @ 15770:77e97f159554 v8.1.0892

patch 8.1.0892: failure when closing a window when location list is in use commit https://github.com/vim/vim/commit/eeb1b9c7ed33c152e041a286d79bf3ed00d80e40 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Feb 10 22:59:04 2019 +0100 patch 8.1.0892: failure when closing a window when location list is in use Problem: Failure when closing a window when location list is in use. Solution: Handle the situation gracefully. Make sure memory for 'switchbuf' is not freed at the wrong time. (Yegappan Lakshmanan, closes #3928)
author Bram Moolenaar <Bram@vim.org>
date Sun, 10 Feb 2019 23:00:05 +0100
parents 2fe4a503c5ad
children f376cd250b07
comparison
equal deleted inserted replaced
15769:86912a1ebf3d 15770:77e97f159554
1897 qi = *pqi; 1897 qi = *pqi;
1898 if (qi == NULL) 1898 if (qi == NULL)
1899 return; 1899 return;
1900 *pqi = NULL; // Remove reference to this list 1900 *pqi = NULL; // Remove reference to this list
1901 1901
1902 // If the location list is still in use, then queue the delete request
1903 // to be processed later.
1904 if (quickfix_busy > 0)
1905 {
1906 locstack_queue_delreq(qi);
1907 return;
1908 }
1909
1902 qi->qf_refcount--; 1910 qi->qf_refcount--;
1903 if (qi->qf_refcount < 1) 1911 if (qi->qf_refcount < 1)
1904 { 1912 {
1905 // No references to this location list. 1913 // No references to this location list.
1906 // If the location list is still in use, then queue the delete request 1914 // If the quickfix window buffer is loaded, then wipe it
1907 // to be processed later. 1915 wipe_qf_buffer(qi);
1908 if (quickfix_busy > 0) 1916
1909 locstack_queue_delreq(qi); 1917 for (i = 0; i < qi->qf_listcount; ++i)
1910 else 1918 qf_free(&qi->qf_lists[i]);
1911 { 1919 vim_free(qi);
1912 // If the quickfix window buffer is loaded, then wipe it
1913 wipe_qf_buffer(qi);
1914
1915 for (i = 0; i < qi->qf_listcount; ++i)
1916 qf_free(&qi->qf_lists[i]);
1917 vim_free(qi);
1918 }
1919 } 1920 }
1920 } 1921 }
1921 1922
1922 /* 1923 /*
1923 * Free all the quickfix/location lists in the stack. 1924 * Free all the quickfix/location lists in the stack.
3016 static int 3017 static int
3017 qf_jump_edit_buffer( 3018 qf_jump_edit_buffer(
3018 qf_info_T *qi, 3019 qf_info_T *qi,
3019 qfline_T *qf_ptr, 3020 qfline_T *qf_ptr,
3020 int forceit, 3021 int forceit,
3021 win_T *oldwin, 3022 int prev_winid,
3022 int *opened_window) 3023 int *opened_window)
3023 { 3024 {
3024 qf_list_T *qfl = &qi->qf_lists[qi->qf_curlist]; 3025 qf_list_T *qfl = &qi->qf_lists[qi->qf_curlist];
3025 qfltype_T qfl_type = qfl->qfl_type; 3026 qfltype_T qfl_type = qfl->qfl_type;
3026 int retval = OK; 3027 int retval = OK;
3037 return FAIL; 3038 return FAIL;
3038 } 3039 }
3039 3040
3040 retval = do_ecmd(qf_ptr->qf_fnum, NULL, NULL, NULL, (linenr_T)1, 3041 retval = do_ecmd(qf_ptr->qf_fnum, NULL, NULL, NULL, (linenr_T)1,
3041 ECMD_HIDE + ECMD_SET_HELP, 3042 ECMD_HIDE + ECMD_SET_HELP,
3042 oldwin == curwin ? curwin : NULL); 3043 prev_winid == curwin->w_id ? curwin : NULL);
3043 } 3044 }
3044 else 3045 else
3045 retval = buflist_getfile(qf_ptr->qf_fnum, 3046 retval = buflist_getfile(qf_ptr->qf_fnum,
3046 (linenr_T)1, GETF_SETMARK | GETF_SWITCH, forceit); 3047 (linenr_T)1, GETF_SETMARK | GETF_SWITCH, forceit);
3047 3048
3048 // If a location list, check whether the associated window is still 3049 // If a location list, check whether the associated window is still
3049 // present. 3050 // present.
3050 if (qfl_type == QFLT_LOCATION && !win_valid_any_tab(oldwin)) 3051 if (qfl_type == QFLT_LOCATION)
3051 { 3052 {
3052 emsg(_("E924: Current window was closed")); 3053 win_T *wp = win_id2wp(prev_winid);
3053 *opened_window = FALSE; 3054 if (wp == NULL && curwin->w_llist != qi)
3054 return NOTDONE; 3055 {
3056 emsg(_("E924: Current window was closed"));
3057 *opened_window = FALSE;
3058 return NOTDONE;
3059 }
3055 } 3060 }
3056 3061
3057 if (qfl_type == QFLT_QUICKFIX && !qflist_valid(NULL, save_qfid)) 3062 if (qfl_type == QFLT_QUICKFIX && !qflist_valid(NULL, save_qfid))
3058 { 3063 {
3059 emsg(_("E925: Current quickfix was changed")); 3064 emsg(_("E925: Current quickfix was changed"));
3209 qf_jump_to_buffer( 3214 qf_jump_to_buffer(
3210 qf_info_T *qi, 3215 qf_info_T *qi,
3211 int qf_index, 3216 int qf_index,
3212 qfline_T *qf_ptr, 3217 qfline_T *qf_ptr,
3213 int forceit, 3218 int forceit,
3214 win_T *oldwin, 3219 int prev_winid,
3215 int *opened_window, 3220 int *opened_window,
3216 int openfold, 3221 int openfold,
3217 int print_message) 3222 int print_message)
3218 { 3223 {
3219 buf_T *old_curbuf; 3224 buf_T *old_curbuf;
3225 old_curbuf = curbuf; 3230 old_curbuf = curbuf;
3226 old_lnum = curwin->w_cursor.lnum; 3231 old_lnum = curwin->w_cursor.lnum;
3227 3232
3228 if (qf_ptr->qf_fnum != 0) 3233 if (qf_ptr->qf_fnum != 0)
3229 { 3234 {
3230 retval = qf_jump_edit_buffer(qi, qf_ptr, forceit, oldwin, 3235 retval = qf_jump_edit_buffer(qi, qf_ptr, forceit, prev_winid,
3231 opened_window); 3236 opened_window);
3232 if (retval != OK) 3237 if (retval != OK)
3233 return retval; 3238 return retval;
3234 } 3239 }
3235 3240
3285 qfline_T *old_qf_ptr; 3290 qfline_T *old_qf_ptr;
3286 int qf_index; 3291 int qf_index;
3287 int old_qf_index; 3292 int old_qf_index;
3288 char_u *old_swb = p_swb; 3293 char_u *old_swb = p_swb;
3289 unsigned old_swb_flags = swb_flags; 3294 unsigned old_swb_flags = swb_flags;
3295 int prev_winid;
3290 int opened_window = FALSE; 3296 int opened_window = FALSE;
3291 win_T *oldwin = curwin;
3292 int print_message = TRUE; 3297 int print_message = TRUE;
3293 #ifdef FEAT_FOLDING 3298 #ifdef FEAT_FOLDING
3294 int old_KeyTyped = KeyTyped; // getting file may reset it 3299 int old_KeyTyped = KeyTyped; // getting file may reset it
3295 #endif 3300 #endif
3296 int retval = OK; 3301 int retval = OK;
3302 { 3307 {
3303 emsg(_(e_quickfix)); 3308 emsg(_(e_quickfix));
3304 return; 3309 return;
3305 } 3310 }
3306 3311
3312 incr_quickfix_busy();
3313
3307 qfl = &qi->qf_lists[qi->qf_curlist]; 3314 qfl = &qi->qf_lists[qi->qf_curlist];
3308 3315
3309 qf_ptr = qfl->qf_ptr; 3316 qf_ptr = qfl->qf_ptr;
3310 old_qf_ptr = qf_ptr; 3317 old_qf_ptr = qf_ptr;
3311 qf_index = qfl->qf_index; 3318 qf_index = qfl->qf_index;
3323 if (qf_win_pos_update(qi, old_qf_index)) 3330 if (qf_win_pos_update(qi, old_qf_index))
3324 // No need to print the error message if it's visible in the error 3331 // No need to print the error message if it's visible in the error
3325 // window 3332 // window
3326 print_message = FALSE; 3333 print_message = FALSE;
3327 3334
3335 prev_winid = curwin->w_id;
3336
3328 retval = qf_jump_open_window(qi, qf_ptr, newwin, &opened_window); 3337 retval = qf_jump_open_window(qi, qf_ptr, newwin, &opened_window);
3329 if (retval == FAIL) 3338 if (retval == FAIL)
3330 goto failed; 3339 goto failed;
3331 if (retval == NOTDONE) 3340 if (retval == NOTDONE)
3332 goto theend; 3341 goto theend;
3333 3342
3334 retval = qf_jump_to_buffer(qi, qf_index, qf_ptr, forceit, oldwin, 3343 retval = qf_jump_to_buffer(qi, qf_index, qf_ptr, forceit, prev_winid,
3335 &opened_window, old_KeyTyped, print_message); 3344 &opened_window, old_KeyTyped, print_message);
3336 if (retval == NOTDONE) 3345 if (retval == NOTDONE)
3337 { 3346 {
3338 // Quickfix/location list is freed by an autocmd 3347 // Quickfix/location list is freed by an autocmd
3339 qi = NULL; 3348 qi = NULL;
3357 if (qi != NULL) 3366 if (qi != NULL)
3358 { 3367 {
3359 qfl->qf_ptr = qf_ptr; 3368 qfl->qf_ptr = qf_ptr;
3360 qfl->qf_index = qf_index; 3369 qfl->qf_index = qf_index;
3361 } 3370 }
3362 if (p_swb != old_swb && opened_window) 3371 if (p_swb != old_swb)
3363 { 3372 {
3364 // Restore old 'switchbuf' value, but not when an autocommand or 3373 // Restore old 'switchbuf' value, but not when an autocommand or
3365 // modeline has changed the value. 3374 // modeline has changed the value.
3366 if (p_swb == empty_option) 3375 if (p_swb == empty_option)
3367 { 3376 {
3369 swb_flags = old_swb_flags; 3378 swb_flags = old_swb_flags;
3370 } 3379 }
3371 else 3380 else
3372 free_string_option(old_swb); 3381 free_string_option(old_swb);
3373 } 3382 }
3383 decr_quickfix_busy();
3374 } 3384 }
3375 3385
3376 // Highlight attributes used for displaying entries from the quickfix list. 3386 // Highlight attributes used for displaying entries from the quickfix list.
3377 static int qfFileAttr; 3387 static int qfFileAttr;
3378 static int qfSepAttr; 3388 static int qfSepAttr;
4002 RESET_BINDING(curwin); 4012 RESET_BINDING(curwin);
4003 4013
4004 if (IS_LL_STACK(qi)) 4014 if (IS_LL_STACK(qi))
4005 { 4015 {
4006 // For the location list window, create a reference to the 4016 // For the location list window, create a reference to the
4007 // location list from the window 'win'. 4017 // location list stack from the window 'win'.
4008 curwin->w_llist_ref = win->w_llist; 4018 curwin->w_llist_ref = qi;
4009 win->w_llist->qf_refcount++; 4019 qi->qf_refcount++;
4010 } 4020 }
4011 4021
4012 if (oldwin != curwin) 4022 if (oldwin != curwin)
4013 oldwin = NULL; // don't store info when in another window 4023 oldwin = NULL; // don't store info when in another window
4014 if (qf_buf != NULL) 4024 if (qf_buf != NULL)