diff --git a/src/ChangeLog b/src/ChangeLog index de472ab51dd..9a239de5b99 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,11 @@ +2012-06-18 Martin Rudalics + + * buffer.c (Fkill_buffer): Don't throw an error when the buffer + gets killed during executing of this function (Bug#11665). Try + to always return Qt when the buffer has been actually killed. + (Vkill_buffer_query_functions): In doc-string say that functions + run by this hook should not change the current buffer. + 2012-06-18 Paul Eggert Fix recently-introduced process.c problems found by static checking. diff --git a/src/buffer.c b/src/buffer.c index c8cbaa25698..e501c9b73cc 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1434,24 +1434,26 @@ No argument or nil as argument means do this for the current buffer. */) DEFVAR_LISP ("kill-buffer-hook", ..., "\ Hook to be run (by `run-hooks', which see) when a buffer is killed.\n\ The buffer being killed will be current while the hook is running.\n\ -See `kill-buffer'." - */ + +Functions run by this hook are supposed to not change the current +buffer. See `kill-buffer'." +*/ DEFUN ("kill-buffer", Fkill_buffer, Skill_buffer, 0, 1, "bKill buffer: ", - doc: /* Kill buffer BUFFER-OR-NAME. + doc: /* Kill the buffer specified by BUFFER-OR-NAME. The argument may be a buffer or the name of an existing buffer. Argument nil or omitted means kill the current buffer. Return t if the buffer is actually killed, nil otherwise. -This function calls `replace-buffer-in-windows' for cleaning up all -windows currently displaying the buffer to be killed. The functions in -`kill-buffer-query-functions' are called with the buffer to be killed as -the current buffer. If any of them returns nil, the buffer is not -killed. The hook `kill-buffer-hook' is run before the buffer is -actually killed. The buffer being killed will be current while the hook -is running. +The functions in `kill-buffer-query-functions' are called with the +buffer to be killed as the current buffer. If any of them returns nil, +the buffer is not killed. The hook `kill-buffer-hook' is run before the +buffer is actually killed. The buffer being killed will be current +while the hook is running. Functions called by any of these hooks are +supposed to not change the current buffer. Any processes that have this buffer as the `process-buffer' are killed -with SIGHUP. */) +with SIGHUP. This function calls `replace-buffer-in-windows' for +cleaning up all windows currently displaying the buffer to be killed. */) (Lisp_Object buffer_or_name) { Lisp_Object buffer; @@ -1505,6 +1507,10 @@ with SIGHUP. */) unbind_to (count, Qnil); } + /* If the hooks have killed the buffer, exit now. */ + if (NILP (BVAR (b, name))) + return Qt; + /* We have no more questions to ask. Verify that it is valid to kill the buffer. This must be done after the questions since anything can happen within do_yes_or_no_p. */ @@ -1513,9 +1519,6 @@ with SIGHUP. */) if (EQ (buffer, XWINDOW (minibuf_window)->buffer)) return Qnil; - if (NILP (BVAR (b, name))) - return Qnil; - /* When we kill a base buffer, kill all its indirect buffers. We do it at this stage so nothing terrible happens if they ask questions or their hooks get errors. */ @@ -1536,6 +1539,10 @@ with SIGHUP. */) } UNGCPRO; + + /* Exit if we now have killed the base buffer (Bug#11665). */ + if (NILP (BVAR (b, name))) + return Qt; } /* Run replace_buffer_in_windows before making another buffer current @@ -1544,9 +1551,12 @@ with SIGHUP. */) buffer. (Bug#10114) */ replace_buffer_in_windows (buffer); - /* Make this buffer not be current. - In the process, notice if this is the sole visible buffer - and give up if so. */ + /* Exit if replacing the buffer in windows has killed our buffer. */ + if (NILP (BVAR (b, name))) + return Qt; + + /* Make this buffer not be current. Exit if it is the sole visible + buffer. */ if (b == current_buffer) { tem = Fother_buffer (buffer, Qnil, Qnil); @@ -1555,15 +1565,12 @@ with SIGHUP. */) return Qnil; } - /* Notice if the buffer to kill is the sole visible buffer - when we're currently in the mini-buffer, and give up if so. */ + /* If the buffer now current is shown in the minibuffer and our buffer + is the sole other buffer give up. */ XSETBUFFER (tem, current_buffer); - if (EQ (tem, XWINDOW (minibuf_window)->buffer)) - { - tem = Fother_buffer (buffer, Qnil, Qnil); - if (EQ (buffer, tem)) - return Qnil; - } + if (EQ (tem, XWINDOW (minibuf_window)->buffer) + && EQ (buffer, Fother_buffer (buffer, Qnil, Qnil))) + return Qnil; /* Now there is no question: we can kill the buffer. */ @@ -1576,11 +1583,10 @@ with SIGHUP. */) kill_buffer_processes (buffer); UNGCPRO; - /* Killing buffer processes may run sentinels which may - have called kill-buffer. */ - + /* Killing buffer processes may run sentinels which may have killed + our buffer. */ if (NILP (BVAR (b, name))) - return Qnil; + return Qt; /* These may run Lisp code and into infinite loops (if someone insisted on circular lists) so allow quitting here. */ @@ -1592,8 +1598,7 @@ with SIGHUP. */) Vinhibit_quit = Qt; /* Remove the buffer from the list of all buffers. */ Vbuffer_alist = Fdelq (Frassq (buffer, Vbuffer_alist), Vbuffer_alist); - /* If replace_buffer_in_windows didn't do its job correctly fix that - now. */ + /* If replace_buffer_in_windows didn't do its job fix that now. */ replace_buffer_in_windows_safely (buffer); Vinhibit_quit = tem; @@ -1611,6 +1616,10 @@ with SIGHUP. */) internal_delete_file (BVAR (b, auto_save_file_name)); } + /* Deleting an auto-save file could have killed our buffer. */ + if (NILP (BVAR (b, name))) + return Qt; + if (b->base_buffer) { /* Unchain all markers that belong to this indirect buffer. @@ -5991,7 +6000,9 @@ Use Custom to set this variable and update the display." */); DEFVAR_LISP ("kill-buffer-query-functions", Vkill_buffer_query_functions, doc: /* List of functions called with no args to query before killing a buffer. The buffer being killed will be current while the functions are running. -If any of them returns nil, the buffer is not killed. */); + +If any of them returns nil, the buffer is not killed. Functions run by +this hook are supposed to not change the current buffer. */); Vkill_buffer_query_functions = Qnil; DEFVAR_LISP ("change-major-mode-hook", Vchange_major_mode_hook,