Commit b7e8d081 authored by Martin Rudalics's avatar Martin Rudalics

Handle cases where buffer gets killed while running Fkill_buffer (Bug#11665).

* 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.
parent 7ea2b339
2012-06-18 Martin Rudalics <rudalics@gmx.at>
* 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 <eggert@cs.ucla.edu>
Fix recently-introduced process.c problems found by static checking.
......
......@@ -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,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment