hush: implement "return NUM in trap sets $? after trap"
function old new delta builtin_return 47 67 +20 check_and_run_traps 243 259 +16 run_pipe 1583 1597 +14 hush_main 1076 1086 +10 run_list 1054 1055 +1 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 5/0 up/down: 61/0) Total: 61 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
d5bfe26c45
commit
bb095f4838
2
shell/ash_test/ash-misc/exitcode_trap3.right
Normal file
2
shell/ash_test/ash-misc/exitcode_trap3.right
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
TERM
|
||||||
|
42:42
|
9
shell/ash_test/ash-misc/exitcode_trap3.tests
Executable file
9
shell/ash_test/ash-misc/exitcode_trap3.tests
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
# "return" in trap should not use last command's exitcode,
|
||||||
|
# but exitcode on entering the trap.
|
||||||
|
trap "echo TERM;return" term
|
||||||
|
f() {
|
||||||
|
(sleep 1; kill $$) &
|
||||||
|
until (exit 42) do (exit 42); done
|
||||||
|
}
|
||||||
|
f
|
||||||
|
echo 42:$?
|
2
shell/ash_test/ash-misc/exitcode_trap4.right
Normal file
2
shell/ash_test/ash-misc/exitcode_trap4.right
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
TERM
|
||||||
|
11:11
|
8
shell/ash_test/ash-misc/exitcode_trap4.tests
Executable file
8
shell/ash_test/ash-misc/exitcode_trap4.tests
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
# "return" in trap sets $? after trap
|
||||||
|
trap "echo TERM;return 11" term
|
||||||
|
f() {
|
||||||
|
(sleep 1; kill $$) &
|
||||||
|
until (exit 42) do (exit 42); done
|
||||||
|
}
|
||||||
|
f
|
||||||
|
echo 11:$?
|
3
shell/ash_test/ash-misc/exitcode_trap5.right
Normal file
3
shell/ash_test/ash-misc/exitcode_trap5.right
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
TERM
|
||||||
|
Nested
|
||||||
|
Zero:0
|
10
shell/ash_test/ash-misc/exitcode_trap5.tests
Executable file
10
shell/ash_test/ash-misc/exitcode_trap5.tests
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
# "return" in trap sets $? after trap...
|
||||||
|
# ...but not a nested one!
|
||||||
|
g() { echo Nested; return 22; }
|
||||||
|
trap "echo TERM;false;g" term
|
||||||
|
f() {
|
||||||
|
(kill $$) &
|
||||||
|
sleep 1
|
||||||
|
}
|
||||||
|
f
|
||||||
|
echo Zero:$?
|
31
shell/hush.c
31
shell/hush.c
@ -988,6 +988,9 @@ struct globals {
|
|||||||
# define G_fatal_sig_mask 0
|
# define G_fatal_sig_mask 0
|
||||||
#endif
|
#endif
|
||||||
#if ENABLE_HUSH_TRAP
|
#if ENABLE_HUSH_TRAP
|
||||||
|
# if ENABLE_HUSH_FUNCTIONS
|
||||||
|
int return_exitcode;
|
||||||
|
# endif
|
||||||
char **traps; /* char *traps[NSIG] */
|
char **traps; /* char *traps[NSIG] */
|
||||||
# define G_traps G.traps
|
# define G_traps G.traps
|
||||||
#else
|
#else
|
||||||
@ -2097,6 +2100,7 @@ static int check_and_run_traps(void)
|
|||||||
} while (sig < NSIG);
|
} while (sig < NSIG);
|
||||||
break;
|
break;
|
||||||
got_sig:
|
got_sig:
|
||||||
|
#if ENABLE_HUSH_TRAP
|
||||||
if (G_traps && G_traps[sig]) {
|
if (G_traps && G_traps[sig]) {
|
||||||
debug_printf_exec("%s: sig:%d handler:'%s'\n", __func__, sig, G.traps[sig]);
|
debug_printf_exec("%s: sig:%d handler:'%s'\n", __func__, sig, G.traps[sig]);
|
||||||
if (G_traps[sig][0]) {
|
if (G_traps[sig][0]) {
|
||||||
@ -2110,12 +2114,18 @@ static int check_and_run_traps(void)
|
|||||||
save_rcode = G.last_exitcode;
|
save_rcode = G.last_exitcode;
|
||||||
builtin_eval(argv);
|
builtin_eval(argv);
|
||||||
free(argv[1]);
|
free(argv[1]);
|
||||||
//FIXME: shouldn't it be set to 128 + sig instead?
|
|
||||||
G.last_exitcode = save_rcode;
|
G.last_exitcode = save_rcode;
|
||||||
|
# if ENABLE_HUSH_FUNCTIONS
|
||||||
|
if (G.return_exitcode >= 0) {
|
||||||
|
debug_printf_exec("trap exitcode:%d\n", G.return_exitcode);
|
||||||
|
G.last_exitcode = G.return_exitcode;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
last_sig = sig;
|
last_sig = sig;
|
||||||
} /* else: "" trap, ignoring signal */
|
} /* else: "" trap, ignoring signal */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
/* not a trap: special action */
|
/* not a trap: special action */
|
||||||
switch (sig) {
|
switch (sig) {
|
||||||
case SIGINT:
|
case SIGINT:
|
||||||
@ -8127,6 +8137,10 @@ static int run_function(const struct function *funcp, char **argv)
|
|||||||
IF_HUSH_LOCAL(leave_var_nest_level();)
|
IF_HUSH_LOCAL(leave_var_nest_level();)
|
||||||
|
|
||||||
G_flag_return_in_progress = sv_flg;
|
G_flag_return_in_progress = sv_flg;
|
||||||
|
# if ENABLE_HUSH_TRAP
|
||||||
|
debug_printf_exec("G.return_exitcode=-1\n");
|
||||||
|
G.return_exitcode = -1; /* invalidate stashed return value */
|
||||||
|
# endif
|
||||||
|
|
||||||
restore_G_args(&sv, argv);
|
restore_G_args(&sv, argv);
|
||||||
|
|
||||||
@ -9628,6 +9642,9 @@ static int run_list(struct pipe *pi)
|
|||||||
debug_printf_exec(": builtin/func exitcode %d\n", rcode);
|
debug_printf_exec(": builtin/func exitcode %d\n", rcode);
|
||||||
G.last_exitcode = rcode;
|
G.last_exitcode = rcode;
|
||||||
check_and_run_traps();
|
check_and_run_traps();
|
||||||
|
#if ENABLE_HUSH_TRAP && ENABLE_HUSH_FUNCTIONS
|
||||||
|
rcode = G.last_exitcode; /* "return" in trap can change it, read back */
|
||||||
|
#endif
|
||||||
#if ENABLE_HUSH_LOOPS
|
#if ENABLE_HUSH_LOOPS
|
||||||
/* Was it "break" or "continue"? */
|
/* Was it "break" or "continue"? */
|
||||||
if (G.flag_break_continue) {
|
if (G.flag_break_continue) {
|
||||||
@ -9684,6 +9701,9 @@ static int run_list(struct pipe *pi)
|
|||||||
check_traps:
|
check_traps:
|
||||||
G.last_exitcode = rcode;
|
G.last_exitcode = rcode;
|
||||||
check_and_run_traps();
|
check_and_run_traps();
|
||||||
|
#if ENABLE_HUSH_TRAP && ENABLE_HUSH_FUNCTIONS
|
||||||
|
rcode = G.last_exitcode; /* "return" in trap can change it, read back */
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle "set -e" */
|
/* Handle "set -e" */
|
||||||
@ -9907,6 +9927,9 @@ int hush_main(int argc, char **argv)
|
|||||||
INIT_G();
|
INIT_G();
|
||||||
if (EXIT_SUCCESS != 0) /* if EXIT_SUCCESS == 0, it is already done */
|
if (EXIT_SUCCESS != 0) /* if EXIT_SUCCESS == 0, it is already done */
|
||||||
G.last_exitcode = EXIT_SUCCESS;
|
G.last_exitcode = EXIT_SUCCESS;
|
||||||
|
#if ENABLE_HUSH_TRAP && ENABLE_HUSH_FUNCTIONS
|
||||||
|
G.return_exitcode = -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if ENABLE_HUSH_FAST
|
#if ENABLE_HUSH_FAST
|
||||||
G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */
|
G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */
|
||||||
@ -11745,6 +11768,12 @@ static int FAST_FUNC builtin_return(char **argv)
|
|||||||
* 255 <== we also do this
|
* 255 <== we also do this
|
||||||
*/
|
*/
|
||||||
rc = parse_numeric_argv1(argv, G.last_exitcode, 0);
|
rc = parse_numeric_argv1(argv, G.last_exitcode, 0);
|
||||||
|
# if ENABLE_HUSH_TRAP
|
||||||
|
if (argv[1]) { /* "return ARG" inside a running trap sets $? */
|
||||||
|
debug_printf_exec("G.return_exitcode=%d\n", rc);
|
||||||
|
G.return_exitcode = rc;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
2
shell/hush_test/hush-misc/exitcode_trap3.right
Normal file
2
shell/hush_test/hush-misc/exitcode_trap3.right
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
TERM
|
||||||
|
42:42
|
9
shell/hush_test/hush-misc/exitcode_trap3.tests
Executable file
9
shell/hush_test/hush-misc/exitcode_trap3.tests
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
# "return" in trap should not use last command's exitcode,
|
||||||
|
# but exitcode on entering the trap.
|
||||||
|
trap "echo TERM;return" term
|
||||||
|
f() {
|
||||||
|
(sleep 1; kill $$) &
|
||||||
|
until (exit 42) do (exit 42); done
|
||||||
|
}
|
||||||
|
f
|
||||||
|
echo 42:$?
|
2
shell/hush_test/hush-misc/exitcode_trap4.right
Normal file
2
shell/hush_test/hush-misc/exitcode_trap4.right
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
TERM
|
||||||
|
11:11
|
8
shell/hush_test/hush-misc/exitcode_trap4.tests
Executable file
8
shell/hush_test/hush-misc/exitcode_trap4.tests
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
# "return" in trap sets $? after trap
|
||||||
|
trap "echo TERM;return 11" term
|
||||||
|
f() {
|
||||||
|
(sleep 1; kill $$) &
|
||||||
|
until (exit 42) do (exit 42); done
|
||||||
|
}
|
||||||
|
f
|
||||||
|
echo 11:$?
|
3
shell/hush_test/hush-misc/exitcode_trap5.right
Normal file
3
shell/hush_test/hush-misc/exitcode_trap5.right
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
TERM
|
||||||
|
Nested
|
||||||
|
Zero:0
|
10
shell/hush_test/hush-misc/exitcode_trap5.tests
Executable file
10
shell/hush_test/hush-misc/exitcode_trap5.tests
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
# "return" in trap sets $? after trap...
|
||||||
|
# ...but not a nested one!
|
||||||
|
g() { echo Nested; return 22; }
|
||||||
|
trap "echo TERM;false;g" term
|
||||||
|
f() {
|
||||||
|
(kill $$) &
|
||||||
|
sleep 1
|
||||||
|
}
|
||||||
|
f
|
||||||
|
echo Zero:$?
|
Loading…
Reference in New Issue
Block a user