diff options
| author | Martin Rudalics | 2012-06-18 09:20:19 +0200 |
|---|---|---|
| committer | Martin Rudalics | 2012-06-18 09:20:19 +0200 |
| commit | b7e8d081674c24b19c5ee39892a72aef25c1dfcc (patch) | |
| tree | f53f81a0692d7e47235db17bfb51cf6ef2bfd895 /src/buffer.c | |
| parent | 7ea2b33947b401d506d10bf47721278a2b174410 (diff) | |
| download | emacs-b7e8d081674c24b19c5ee39892a72aef25c1dfcc.tar.gz emacs-b7e8d081674c24b19c5ee39892a72aef25c1dfcc.zip | |
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.
Diffstat (limited to 'src/buffer.c')
| -rw-r--r-- | src/buffer.c | 75 |
1 files changed, 43 insertions, 32 deletions
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. */) | |||
| 1434 | DEFVAR_LISP ("kill-buffer-hook", ..., "\ | 1434 | DEFVAR_LISP ("kill-buffer-hook", ..., "\ |
| 1435 | Hook to be run (by `run-hooks', which see) when a buffer is killed.\n\ | 1435 | Hook to be run (by `run-hooks', which see) when a buffer is killed.\n\ |
| 1436 | The buffer being killed will be current while the hook is running.\n\ | 1436 | The buffer being killed will be current while the hook is running.\n\ |
| 1437 | See `kill-buffer'." | 1437 | |
| 1438 | */ | 1438 | Functions run by this hook are supposed to not change the current |
| 1439 | buffer. See `kill-buffer'." | ||
| 1440 | */ | ||
| 1439 | DEFUN ("kill-buffer", Fkill_buffer, Skill_buffer, 0, 1, "bKill buffer: ", | 1441 | DEFUN ("kill-buffer", Fkill_buffer, Skill_buffer, 0, 1, "bKill buffer: ", |
| 1440 | doc: /* Kill buffer BUFFER-OR-NAME. | 1442 | doc: /* Kill the buffer specified by BUFFER-OR-NAME. |
| 1441 | The argument may be a buffer or the name of an existing buffer. | 1443 | The argument may be a buffer or the name of an existing buffer. |
| 1442 | Argument nil or omitted means kill the current buffer. Return t if the | 1444 | Argument nil or omitted means kill the current buffer. Return t if the |
| 1443 | buffer is actually killed, nil otherwise. | 1445 | buffer is actually killed, nil otherwise. |
| 1444 | 1446 | ||
| 1445 | This function calls `replace-buffer-in-windows' for cleaning up all | 1447 | The functions in `kill-buffer-query-functions' are called with the |
| 1446 | windows currently displaying the buffer to be killed. The functions in | 1448 | buffer to be killed as the current buffer. If any of them returns nil, |
| 1447 | `kill-buffer-query-functions' are called with the buffer to be killed as | 1449 | the buffer is not killed. The hook `kill-buffer-hook' is run before the |
| 1448 | the current buffer. If any of them returns nil, the buffer is not | 1450 | buffer is actually killed. The buffer being killed will be current |
| 1449 | killed. The hook `kill-buffer-hook' is run before the buffer is | 1451 | while the hook is running. Functions called by any of these hooks are |
| 1450 | actually killed. The buffer being killed will be current while the hook | 1452 | supposed to not change the current buffer. |
| 1451 | is running. | ||
| 1452 | 1453 | ||
| 1453 | Any processes that have this buffer as the `process-buffer' are killed | 1454 | Any processes that have this buffer as the `process-buffer' are killed |
| 1454 | with SIGHUP. */) | 1455 | with SIGHUP. This function calls `replace-buffer-in-windows' for |
| 1456 | cleaning up all windows currently displaying the buffer to be killed. */) | ||
| 1455 | (Lisp_Object buffer_or_name) | 1457 | (Lisp_Object buffer_or_name) |
| 1456 | { | 1458 | { |
| 1457 | Lisp_Object buffer; | 1459 | Lisp_Object buffer; |
| @@ -1505,6 +1507,10 @@ with SIGHUP. */) | |||
| 1505 | unbind_to (count, Qnil); | 1507 | unbind_to (count, Qnil); |
| 1506 | } | 1508 | } |
| 1507 | 1509 | ||
| 1510 | /* If the hooks have killed the buffer, exit now. */ | ||
| 1511 | if (NILP (BVAR (b, name))) | ||
| 1512 | return Qt; | ||
| 1513 | |||
| 1508 | /* We have no more questions to ask. Verify that it is valid | 1514 | /* We have no more questions to ask. Verify that it is valid |
| 1509 | to kill the buffer. This must be done after the questions | 1515 | to kill the buffer. This must be done after the questions |
| 1510 | since anything can happen within do_yes_or_no_p. */ | 1516 | since anything can happen within do_yes_or_no_p. */ |
| @@ -1513,9 +1519,6 @@ with SIGHUP. */) | |||
| 1513 | if (EQ (buffer, XWINDOW (minibuf_window)->buffer)) | 1519 | if (EQ (buffer, XWINDOW (minibuf_window)->buffer)) |
| 1514 | return Qnil; | 1520 | return Qnil; |
| 1515 | 1521 | ||
| 1516 | if (NILP (BVAR (b, name))) | ||
| 1517 | return Qnil; | ||
| 1518 | |||
| 1519 | /* When we kill a base buffer, kill all its indirect buffers. | 1522 | /* When we kill a base buffer, kill all its indirect buffers. |
| 1520 | We do it at this stage so nothing terrible happens if they | 1523 | We do it at this stage so nothing terrible happens if they |
| 1521 | ask questions or their hooks get errors. */ | 1524 | ask questions or their hooks get errors. */ |
| @@ -1536,6 +1539,10 @@ with SIGHUP. */) | |||
| 1536 | } | 1539 | } |
| 1537 | 1540 | ||
| 1538 | UNGCPRO; | 1541 | UNGCPRO; |
| 1542 | |||
| 1543 | /* Exit if we now have killed the base buffer (Bug#11665). */ | ||
| 1544 | if (NILP (BVAR (b, name))) | ||
| 1545 | return Qt; | ||
| 1539 | } | 1546 | } |
| 1540 | 1547 | ||
| 1541 | /* Run replace_buffer_in_windows before making another buffer current | 1548 | /* Run replace_buffer_in_windows before making another buffer current |
| @@ -1544,9 +1551,12 @@ with SIGHUP. */) | |||
| 1544 | buffer. (Bug#10114) */ | 1551 | buffer. (Bug#10114) */ |
| 1545 | replace_buffer_in_windows (buffer); | 1552 | replace_buffer_in_windows (buffer); |
| 1546 | 1553 | ||
| 1547 | /* Make this buffer not be current. | 1554 | /* Exit if replacing the buffer in windows has killed our buffer. */ |
| 1548 | In the process, notice if this is the sole visible buffer | 1555 | if (NILP (BVAR (b, name))) |
| 1549 | and give up if so. */ | 1556 | return Qt; |
| 1557 | |||
| 1558 | /* Make this buffer not be current. Exit if it is the sole visible | ||
| 1559 | buffer. */ | ||
| 1550 | if (b == current_buffer) | 1560 | if (b == current_buffer) |
| 1551 | { | 1561 | { |
| 1552 | tem = Fother_buffer (buffer, Qnil, Qnil); | 1562 | tem = Fother_buffer (buffer, Qnil, Qnil); |
| @@ -1555,15 +1565,12 @@ with SIGHUP. */) | |||
| 1555 | return Qnil; | 1565 | return Qnil; |
| 1556 | } | 1566 | } |
| 1557 | 1567 | ||
| 1558 | /* Notice if the buffer to kill is the sole visible buffer | 1568 | /* If the buffer now current is shown in the minibuffer and our buffer |
| 1559 | when we're currently in the mini-buffer, and give up if so. */ | 1569 | is the sole other buffer give up. */ |
| 1560 | XSETBUFFER (tem, current_buffer); | 1570 | XSETBUFFER (tem, current_buffer); |
| 1561 | if (EQ (tem, XWINDOW (minibuf_window)->buffer)) | 1571 | if (EQ (tem, XWINDOW (minibuf_window)->buffer) |
| 1562 | { | 1572 | && EQ (buffer, Fother_buffer (buffer, Qnil, Qnil))) |
| 1563 | tem = Fother_buffer (buffer, Qnil, Qnil); | 1573 | return Qnil; |
| 1564 | if (EQ (buffer, tem)) | ||
| 1565 | return Qnil; | ||
| 1566 | } | ||
| 1567 | 1574 | ||
| 1568 | /* Now there is no question: we can kill the buffer. */ | 1575 | /* Now there is no question: we can kill the buffer. */ |
| 1569 | 1576 | ||
| @@ -1576,11 +1583,10 @@ with SIGHUP. */) | |||
| 1576 | kill_buffer_processes (buffer); | 1583 | kill_buffer_processes (buffer); |
| 1577 | UNGCPRO; | 1584 | UNGCPRO; |
| 1578 | 1585 | ||
| 1579 | /* Killing buffer processes may run sentinels which may | 1586 | /* Killing buffer processes may run sentinels which may have killed |
| 1580 | have called kill-buffer. */ | 1587 | our buffer. */ |
| 1581 | |||
| 1582 | if (NILP (BVAR (b, name))) | 1588 | if (NILP (BVAR (b, name))) |
| 1583 | return Qnil; | 1589 | return Qt; |
| 1584 | 1590 | ||
| 1585 | /* These may run Lisp code and into infinite loops (if someone | 1591 | /* These may run Lisp code and into infinite loops (if someone |
| 1586 | insisted on circular lists) so allow quitting here. */ | 1592 | insisted on circular lists) so allow quitting here. */ |
| @@ -1592,8 +1598,7 @@ with SIGHUP. */) | |||
| 1592 | Vinhibit_quit = Qt; | 1598 | Vinhibit_quit = Qt; |
| 1593 | /* Remove the buffer from the list of all buffers. */ | 1599 | /* Remove the buffer from the list of all buffers. */ |
| 1594 | Vbuffer_alist = Fdelq (Frassq (buffer, Vbuffer_alist), Vbuffer_alist); | 1600 | Vbuffer_alist = Fdelq (Frassq (buffer, Vbuffer_alist), Vbuffer_alist); |
| 1595 | /* If replace_buffer_in_windows didn't do its job correctly fix that | 1601 | /* If replace_buffer_in_windows didn't do its job fix that now. */ |
| 1596 | now. */ | ||
| 1597 | replace_buffer_in_windows_safely (buffer); | 1602 | replace_buffer_in_windows_safely (buffer); |
| 1598 | Vinhibit_quit = tem; | 1603 | Vinhibit_quit = tem; |
| 1599 | 1604 | ||
| @@ -1611,6 +1616,10 @@ with SIGHUP. */) | |||
| 1611 | internal_delete_file (BVAR (b, auto_save_file_name)); | 1616 | internal_delete_file (BVAR (b, auto_save_file_name)); |
| 1612 | } | 1617 | } |
| 1613 | 1618 | ||
| 1619 | /* Deleting an auto-save file could have killed our buffer. */ | ||
| 1620 | if (NILP (BVAR (b, name))) | ||
| 1621 | return Qt; | ||
| 1622 | |||
| 1614 | if (b->base_buffer) | 1623 | if (b->base_buffer) |
| 1615 | { | 1624 | { |
| 1616 | /* Unchain all markers that belong to this indirect buffer. | 1625 | /* Unchain all markers that belong to this indirect buffer. |
| @@ -5991,7 +6000,9 @@ Use Custom to set this variable and update the display." */); | |||
| 5991 | DEFVAR_LISP ("kill-buffer-query-functions", Vkill_buffer_query_functions, | 6000 | DEFVAR_LISP ("kill-buffer-query-functions", Vkill_buffer_query_functions, |
| 5992 | doc: /* List of functions called with no args to query before killing a buffer. | 6001 | doc: /* List of functions called with no args to query before killing a buffer. |
| 5993 | The buffer being killed will be current while the functions are running. | 6002 | The buffer being killed will be current while the functions are running. |
| 5994 | If any of them returns nil, the buffer is not killed. */); | 6003 | |
| 6004 | If any of them returns nil, the buffer is not killed. Functions run by | ||
| 6005 | this hook are supposed to not change the current buffer. */); | ||
| 5995 | Vkill_buffer_query_functions = Qnil; | 6006 | Vkill_buffer_query_functions = Qnil; |
| 5996 | 6007 | ||
| 5997 | DEFVAR_LISP ("change-major-mode-hook", Vchange_major_mode_hook, | 6008 | DEFVAR_LISP ("change-major-mode-hook", Vchange_major_mode_hook, |