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:
		
							
								
								
									
										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 | ||||
| #endif | ||||
| #if ENABLE_HUSH_TRAP | ||||
| # if ENABLE_HUSH_FUNCTIONS | ||||
| 	int return_exitcode; | ||||
| # endif | ||||
| 	char **traps; /* char *traps[NSIG] */ | ||||
| # define G_traps G.traps | ||||
| #else | ||||
| @@ -2097,6 +2100,7 @@ static int check_and_run_traps(void) | ||||
| 		} while (sig < NSIG); | ||||
| 		break; | ||||
|  got_sig: | ||||
| #if ENABLE_HUSH_TRAP | ||||
| 		if (G_traps && G_traps[sig]) { | ||||
| 			debug_printf_exec("%s: sig:%d handler:'%s'\n", __func__, sig, G.traps[sig]); | ||||
| 			if (G_traps[sig][0]) { | ||||
| @@ -2110,12 +2114,18 @@ static int check_and_run_traps(void) | ||||
| 				save_rcode = G.last_exitcode; | ||||
| 				builtin_eval(argv); | ||||
| 				free(argv[1]); | ||||
| //FIXME: shouldn't it be set to 128 + sig instead? | ||||
| 				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; | ||||
| 			} /* else: "" trap, ignoring signal */ | ||||
| 			continue; | ||||
| 		} | ||||
| #endif | ||||
| 		/* not a trap: special action */ | ||||
| 		switch (sig) { | ||||
| 		case SIGINT: | ||||
| @@ -8127,6 +8137,10 @@ static int run_function(const struct function *funcp, char **argv) | ||||
| 	IF_HUSH_LOCAL(leave_var_nest_level();) | ||||
|  | ||||
| 	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); | ||||
|  | ||||
| @@ -9628,6 +9642,9 @@ static int run_list(struct pipe *pi) | ||||
| 			debug_printf_exec(": builtin/func exitcode %d\n", rcode); | ||||
| 			G.last_exitcode = rcode; | ||||
| 			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 | ||||
| 			/* Was it "break" or "continue"? */ | ||||
| 			if (G.flag_break_continue) { | ||||
| @@ -9684,6 +9701,9 @@ static int run_list(struct pipe *pi) | ||||
|  check_traps: | ||||
| 			G.last_exitcode = rcode; | ||||
| 			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" */ | ||||
| @@ -9907,6 +9927,9 @@ int hush_main(int argc, char **argv) | ||||
| 	INIT_G(); | ||||
| 	if (EXIT_SUCCESS != 0) /* if EXIT_SUCCESS == 0, it is already done */ | ||||
| 		G.last_exitcode = EXIT_SUCCESS; | ||||
| #if ENABLE_HUSH_TRAP && ENABLE_HUSH_FUNCTIONS | ||||
| 	G.return_exitcode = -1; | ||||
| #endif | ||||
|  | ||||
| #if ENABLE_HUSH_FAST | ||||
| 	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 | ||||
| 	 */ | ||||
| 	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; | ||||
| } | ||||
| #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:$? | ||||
		Reference in New Issue
	
	Block a user