summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog3
-rw-r--r--Src/builtin.c11
-rw-r--r--Src/init.c9
3 files changed, 23 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index ee39f58f9..9f46838c1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
2006-11-08 Peter Stephenson <pws@csr.com>
+ * 22983: Src/builtin.c, Src/init.c: exit could loop for ever
+ in two different ways (but not at the same time).
+
* 22978 (tweaked): Doc/Zsh/func.yo, Doc/Zsh/options.yo,
Src/builtin.c, Src/init.c, Src/utils.c, Src/Zle/zle_main.c,
Test/A05execution.ztst: use <hook>_functions array variables for
diff --git a/Src/builtin.c b/Src/builtin.c
index adb0f6ee2..ff40c8b70 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -4391,6 +4391,10 @@ zexit(int val, int from_where)
{
static int in_exit;
+ /* Don't do anything recursively: see below */
+ if (in_exit == -1)
+ return;
+
if (isset(MONITOR) && !stopmsg && from_where != 1) {
scanjobs(); /* check if jobs need printing */
if (isset(CHECKJOBS))
@@ -4400,9 +4404,16 @@ zexit(int val, int from_where)
return;
}
}
+ /* Positive in_exit means we have been here before */
if (from_where == 2 || (in_exit++ && from_where))
return;
+ /*
+ * We're now committed to exiting. Set in_exit to -1 to
+ * indicate we shouldn't do any recursive processing.
+ */
+ in_exit = -1;
+
if (isset(MONITOR)) {
/* send SIGHUP to any jobs left running */
killrunjobs(from_where == 1);
diff --git a/Src/init.c b/Src/init.c
index fad36bf0f..b987f1399 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -131,6 +131,15 @@ loop(int toplevel, int justonce)
(tok == LEXERR && (!isset(SHINSTDIN) || !toplevel)) ||
justonce)
break;
+ if (exit_pending) {
+ /*
+ * Something down there (a ZLE function?) decided
+ * to exit when there was stuff to clear up.
+ * Handle that now.
+ */
+ stopmsg = 1;
+ zexit(exit_pending >> 1, 0);
+ }
if (tok == LEXERR && !lastval)
lastval = 1;
continue;