From 0e1e25fb0a95ac5be411fbf25c8e25e1008c0d3f Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Fri, 28 May 2010 21:07:08 +0200
Subject: [PATCH] Don't execute some autocommands when v:dying is 2 or more.

---
 runtime/doc/autocmd.txt  |  8 ++++++
 runtime/doc/eval.txt     |  4 ++-
 runtime/doc/todo.txt     |  3 ---
 runtime/doc/version7.txt |  4 +++
 src/main.c               | 57 ++++++++++++++++++++++------------------
 5 files changed, 46 insertions(+), 30 deletions(-)

diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt
index c1cbab8334..a23032cd1e 100644
--- a/runtime/doc/autocmd.txt
+++ b/runtime/doc/autocmd.txt
@@ -401,6 +401,8 @@ BufUnload			Before unloading a buffer.  This is when the
 				buffer being unloaded "<afile>".
 				Don't change to another buffer, it will cause
 				problems.
+				When exiting and v:dying is 2 or more this
+				event is not triggered.
 							*BufWinEnter*
 BufWinEnter			After a buffer is displayed in a window.  This
 				can be when the buffer is loaded (after
@@ -422,6 +424,8 @@ BufWinLeave			Before a buffer is removed from a window.
 				NOTE: When this autocommand is executed, the
 				current buffer "%" may be different from the
 				buffer being unloaded "<afile>".
+				When exiting and v:dying is 2 or more this
+				event is not triggered.
 							*BufWipeout*
 BufWipeout			Before completely deleting a buffer.  The
 				BufUnload and BufDelete events may be called
@@ -799,6 +803,8 @@ VimLeave			Before exiting Vim, just after writing the
 				.viminfo file.  Executed only once, like
 				VimLeavePre.
 				To detect an abnormal exit use |v:dying|.
+				When v:dying is 2 or more this event is not
+				triggered.
 							*VimLeavePre*
 VimLeavePre			Before exiting Vim, just before writing the
 				.viminfo file.  This is executed only once,
@@ -807,6 +813,8 @@ VimLeavePre			Before exiting Vim, just before writing the
 				Mostly useful with a "*" pattern. >
 	:autocmd VimLeavePre * call CleanupStuff()
 <				To detect an abnormal exit use |v:dying|.
+				When v:dying is 2 or more this event is not
+				triggered.
 							*VimResized*
 VimResized			After the Vim window was resized, thus 'lines'
 				and/or 'columns' changed.  Not when starting
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 2a2d601551..08b79bb784 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1348,7 +1348,9 @@ v:dying		Normally zero.	When a deadly signal is caught it's set to
 		terminate normally. {only works on Unix}
 		Example: >
 	:au VimLeave * if v:dying | echo "\nAAAAaaaarrrggghhhh!!!\n" | endif
-<
+<		Note: if another deadly signal is caught when v:dying is one,
+		VimLeave autocommands will not be executed.
+
 					*v:errmsg* *errmsg-variable*
 v:errmsg	Last given error message.  It's allowed to set this variable.
 		Example: >
diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt
index e0a6159446..30fb99dc9c 100644
--- a/runtime/doc/todo.txt
+++ b/runtime/doc/todo.txt
@@ -30,9 +30,6 @@ be worked on, but only if you sponsor Vim development.  See |sponsor|.
 							*known-bugs*
 -------------------- Known bugs and current work -----------------------
 
-When Vim crashes it may run out of stack while executing autocommands.  Patch
-to not run autocommands when leaving Vim? (James Vega, 2010 May 23)
-
 Patch for invalid mem access in completion. (Dominique Pelle, 2010 May 26)
 
 Invalid memory access when deleting funcref variable.  Patch by Lech Lorens,
diff --git a/runtime/doc/version7.txt b/runtime/doc/version7.txt
index d59b622649..f469ac0f08 100644
--- a/runtime/doc/version7.txt
+++ b/runtime/doc/version7.txt
@@ -7166,6 +7166,10 @@ don't save what you see.  This could result in work being lost.  Now the text
 after recovery is compared to the original file contents.  When they differ
 the buffer is marked as modified.
 
+When Vim is exiting because of a deadly signal, when v:dying is 2 or more,
+VimLeavePre, VimLeave, BufWinLeave and BufUnload autocommands are not
+executed.
+
 
 Added							*added-7.3*
 -----
diff --git a/src/main.c b/src/main.c
index ec7675e47a..f4e1fde195 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1276,40 +1276,44 @@ getout(exitval)
 #endif
 
 #ifdef FEAT_AUTOCMD
-    /* Trigger BufWinLeave for all windows, but only once per buffer. */
-# if defined FEAT_WINDOWS
-    for (tp = first_tabpage; tp != NULL; tp = next_tp)
+    if (get_vim_var_nr(VV_DYING) <= 1)
     {
-	next_tp = tp->tp_next;
-	for (wp = (tp == curtab)
-		    ? firstwin : tp->tp_firstwin; wp != NULL; wp = wp->w_next)
+	/* Trigger BufWinLeave for all windows, but only once per buffer. */
+# if defined FEAT_WINDOWS
+	for (tp = first_tabpage; tp != NULL; tp = next_tp)
 	{
-	    buf = wp->w_buffer;
-	    if (buf->b_changedtick != -1)
+	    next_tp = tp->tp_next;
+	    for (wp = (tp == curtab)
+		    ? firstwin : tp->tp_firstwin; wp != NULL; wp = wp->w_next)
 	    {
-		apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname,
-								  FALSE, buf);
-		buf->b_changedtick = -1;    /* note that we did it already */
-		/* start all over, autocommands may mess up the lists */
-		next_tp = first_tabpage;
-		break;
+		buf = wp->w_buffer;
+		if (buf->b_changedtick != -1)
+		{
+		    apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname,
+						    buf->b_fname, FALSE, buf);
+		    buf->b_changedtick = -1;    /* note that we did it already */
+		    /* start all over, autocommands may mess up the lists */
+		    next_tp = first_tabpage;
+		    break;
+		}
 	    }
 	}
-    }
 # else
-    apply_autocmds(EVENT_BUFWINLEAVE, curbuf, curbuf->b_fname, FALSE, curbuf);
+	apply_autocmds(EVENT_BUFWINLEAVE, curbuf, curbuf->b_fname,
+							       FALSE, curbuf);
 # endif
 
-    /* Trigger BufUnload for buffers that are loaded */
-    for (buf = firstbuf; buf != NULL; buf = buf->b_next)
-	if (buf->b_ml.ml_mfp != NULL)
-	{
-	    apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname,
+	/* Trigger BufUnload for buffers that are loaded */
+	for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+	    if (buf->b_ml.ml_mfp != NULL)
+	    {
+		apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname,
 								  FALSE, buf);
-	    if (!buf_valid(buf))	/* autocmd may delete the buffer */
-		break;
-	}
-    apply_autocmds(EVENT_VIMLEAVEPRE, NULL, NULL, FALSE, curbuf);
+		if (!buf_valid(buf))	/* autocmd may delete the buffer */
+		    break;
+	    }
+	apply_autocmds(EVENT_VIMLEAVEPRE, NULL, NULL, FALSE, curbuf);
+    }
 #endif
 
 #ifdef FEAT_VIMINFO
@@ -1319,7 +1323,8 @@ getout(exitval)
 #endif
 
 #ifdef FEAT_AUTOCMD
-    apply_autocmds(EVENT_VIMLEAVE, NULL, NULL, FALSE, curbuf);
+    if (get_vim_var_nr(VV_DYING) <= 1)
+	apply_autocmds(EVENT_VIMLEAVE, NULL, NULL, FALSE, curbuf);
 #endif
 
 #ifdef FEAT_PROFILE
-- 
GitLab