[git commit master 1/1] ash: fix signal and "set -e" interaction

Denys Vlasenko vda.linux at googlemail.com
Sat Sep 25 15:15:13 UTC 2010


commit: http://git.busybox.net/busybox/commit/?id=b563f62bbb1c9a6d931924f8fd7c3e52bb3d5875
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 shell/ash.c                              |   19 +++++++++++++------
 shell/ash_test/ash-signals/signal8.right |    3 +++
 shell/ash_test/ash-signals/signal8.tests |   18 ++++++++++++++++++
 shell/ash_test/ash-signals/signal9.right |    3 +++
 shell/ash_test/ash-signals/signal9.tests |   21 +++++++++++++++++++++
 5 files changed, 58 insertions(+), 6 deletions(-)
 create mode 100644 shell/ash_test/ash-signals/signal8.right
 create mode 100755 shell/ash_test/ash-signals/signal8.tests
 create mode 100644 shell/ash_test/ash-signals/signal9.right
 create mode 100755 shell/ash_test/ash-signals/signal9.tests

diff --git a/shell/ash.c b/shell/ash.c
index 9089adc..ea83552 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -8214,7 +8214,7 @@ static int evalstring(char *s, int mask);
 
 /* Called to execute a trap.
  * Single callsite - at the end of evaltree().
- * If we return non-zero, exaltree raises EXEXIT exception.
+ * If we return non-zero, evaltree raises EXEXIT exception.
  *
  * Perhaps we should avoid entering new trap handlers
  * while we are executing a trap handler. [is it a TODO?]
@@ -8404,11 +8404,15 @@ evaltree(union node *n, int flags)
 
  out:
 	exception_handler = savehandler;
+
  out1:
+	/* Order of checks below is important:
+	 * signal handlers trigger before exit caused by "set -e".
+	 */
+	if (pending_sig && dotrap())
+		goto exexit;
 	if (checkexit & exitstatus)
 		evalskip |= SKIPEVAL;
-	else if (pending_sig && dotrap())
-		goto exexit;
 
 	if (flags & EV_EXIT) {
  exexit:
@@ -8740,7 +8744,7 @@ poplocalvars(void)
 	while ((lvp = localvars) != NULL) {
 		localvars = lvp->next;
 		vp = lvp->vp;
-		TRACE(("poplocalvar %s\n", vp ? vp->text : "-"));
+		TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
 		if (vp == NULL) {       /* $- saved */
 			memcpy(optlist, lvp->text, sizeof(optlist));
 			free((char*)lvp->text);
@@ -13009,10 +13013,12 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
 		if (e == EXERROR)
 			exitstatus = 2;
 		s = state;
-		if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
+		if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
 			exitshell();
-		if (e == EXINT)
+		}
+		if (e == EXINT) {
 			outcslow('\n', stderr);
+		}
 
 		popstackmark(&smark);
 		FORCE_INT_ON; /* enable interrupts */
@@ -13105,6 +13111,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
 		_mcleanup();
 	}
 #endif
+	TRACE(("End of main reached\n"));
 	exitshell();
 	/* NOTREACHED */
 }
diff --git a/shell/ash_test/ash-signals/signal8.right b/shell/ash_test/ash-signals/signal8.right
new file mode 100644
index 0000000..39572f3
--- /dev/null
+++ b/shell/ash_test/ash-signals/signal8.right
@@ -0,0 +1,3 @@
+Removing traps
+End of exit_func
+Done: 0
diff --git a/shell/ash_test/ash-signals/signal8.tests b/shell/ash_test/ash-signals/signal8.tests
new file mode 100755
index 0000000..731af74
--- /dev/null
+++ b/shell/ash_test/ash-signals/signal8.tests
@@ -0,0 +1,18 @@
+"$THIS_SH" -c '
+exit_func() {
+    echo "Removing traps"
+    trap - EXIT TERM INT
+    echo "End of exit_func"
+}
+set -e
+trap exit_func EXIT TERM INT
+sleep 2
+exit 77
+' &
+
+sleep 1
+# BUG: ash kills -PGRP, but in non-interactive shell we do not create pgrps!
+# In this case, bash kills by PID, not PGRP.
+kill -TERM %1
+wait
+echo Done: $?
diff --git a/shell/ash_test/ash-signals/signal9.right b/shell/ash_test/ash-signals/signal9.right
new file mode 100644
index 0000000..39572f3
--- /dev/null
+++ b/shell/ash_test/ash-signals/signal9.right
@@ -0,0 +1,3 @@
+Removing traps
+End of exit_func
+Done: 0
diff --git a/shell/ash_test/ash-signals/signal9.tests b/shell/ash_test/ash-signals/signal9.tests
new file mode 100755
index 0000000..18e7101
--- /dev/null
+++ b/shell/ash_test/ash-signals/signal9.tests
@@ -0,0 +1,21 @@
+# Note: the inner script is a test which checks for a different bug
+# (ordering between INT handler and exit on "set -e"),
+# but so far I did not figure out how to simulate it non-interactively.
+
+"$THIS_SH" -c '
+exit_func() {
+    echo "Removing traps"
+    trap - EXIT TERM INT
+    echo "End of exit_func"
+}
+set -e
+trap exit_func EXIT TERM INT
+sleep 2
+exit 77
+' &
+
+child=$!
+sleep 1
+kill -TERM $child
+wait
+echo Done: $?
-- 
1.7.1



More information about the busybox-cvs mailing list