about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Src/exec.c13
-rw-r--r--Test/C03traps.ztst15
2 files changed, 23 insertions, 5 deletions
diff --git a/Src/exec.c b/Src/exec.c
index b0f42ae67..d8501ca68 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -63,7 +63,10 @@ typedef struct funcsave *Funcsave;
 /**/
 int noerrexit;
 
-/* used to suppress ERREXIT or ERRRETURN for one occurrence: 0 or 1 */
+/*
+ * used to suppress ERREXIT and ERRRETURN for the command under evaluation.
+ * 0 or 1
+ */
 
 /**/
 int this_noerrexit;
@@ -1429,10 +1432,7 @@ execlist(Estate state, int dont_change_job, int exiting)
 	    if (!oldnoerrexit)
 		noerrexit = isend ? 0 : NOERREXIT_EXIT | NOERREXIT_RETURN;
 	    if (WC_SUBLIST_FLAGS(code) & WC_SUBLIST_NOT) {
-		/* suppress errexit for "! this_command" */
-		if (isend)
-		    this_noerrexit = 1;
-		/* suppress errexit for ! <list-of-shell-commands> */
+		/* suppress errexit for the commands in ! <list-of-commands> */
 		noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN;
 	    }
 	    switch (WC_SUBLIST_TYPE(code)) {
@@ -1443,6 +1443,9 @@ execlist(Estate state, int dont_change_job, int exiting)
 		else
 		    execpline(state, code, ltype, (ltype & Z_END) && exiting);
 		state->pc = next;
+		/* suppress errexit for the command "! ..." */
+		if (WC_SUBLIST_FLAGS(code) & WC_SUBLIST_NOT)
+		  this_noerrexit = 1;
 		goto sublist_done;
 		break;
 	    case WC_SUBLIST_AND:
diff --git a/Test/C03traps.ztst b/Test/C03traps.ztst
index 4719dfd57..08e24a32e 100644
--- a/Test/C03traps.ztst
+++ b/Test/C03traps.ztst
@@ -721,6 +721,21 @@ F:Must be tested with a top-level script rather than source or function
 >Good
 
   (setopt err_exit
+  ! true
+  print OK
+  )
+0:ERR_EXIT not triggered by "! true"
+>OK
+
+  (setopt err_exit
+  fn() { true }
+  ! fn
+  print OK
+  )
+0:ERR_EXIT not triggered by "! fn"
+>OK
+
+  (setopt err_exit
   false && true
   print OK
   )