diff options
author | Denys Vlasenko | 2015-10-09 16:42:57 +0200 |
---|---|---|
committer | Denys Vlasenko | 2015-10-09 16:42:57 +0200 |
commit | 550bf5b4a418378cd8f9fbbf5252fe57acdacb5a (patch) | |
tree | 7ed13e04cf415be6830363953220d7cffd4580b8 /libbb/vfork_daemon_rexec.c | |
parent | 4cd99e7c6c1af77721b890ed5ae26d747796c4bd (diff) | |
download | busybox-550bf5b4a418378cd8f9fbbf5252fe57acdacb5a.zip busybox-550bf5b4a418378cd8f9fbbf5252fe57acdacb5a.tar.gz |
remove global "jmp_buf die_jmp" from !FEATURE_PREFER_APPLETS builds
function old new delta
xfunc_has_died - 21 +21
sleep_much - 12 +12
sleep10 - 9 +9
die_func - 4 +4
fflush_stdout_and_exit 35 36 +1
builtin_type 121 119 -2
die_sleep 4 - -4
xfunc_die 60 24 -36
hush_main 1128 1011 -117
die_jmp 156 - -156
------------------------------------------------------------------------------
(add/remove: 4/2 grow/shrink: 1/3 up/down: 47/-315) Total: -268 bytes
text data bss dec hex filename
939992 992 17652 958636 ea0ac busybox_old
939880 992 17496 958368 e9fa0 busybox_unstripped
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'libbb/vfork_daemon_rexec.c')
-rw-r--r-- | libbb/vfork_daemon_rexec.c | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index ed1f86f..d6ca7b2 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c @@ -69,28 +69,44 @@ pid_t FAST_FUNC xspawn(char **argv) } #if ENABLE_FEATURE_PREFER_APPLETS +static jmp_buf die_jmp; +static void jump(void) +{ + /* Special case. We arrive here if NOFORK applet + * calls xfunc, which then decides to die. + * We don't die, but jump instead back to caller. + * NOFORK applets still cannot carelessly call xfuncs: + * p = xmalloc(10); + * q = xmalloc(10); // BUG! if this dies, we leak p! + */ + /* | 0x100 allows to pass zero exitcode (longjmp can't pass 0). + * This works because exitcodes are bytes, + * run_nofork_applet() ensures that by "& 0xff" */ + longjmp(die_jmp, xfunc_error_retval | 0x100); +} + struct nofork_save_area { jmp_buf die_jmp; + void (*die_func)(void); const char *applet_name; uint32_t option_mask32; - int die_sleep; uint8_t xfunc_error_retval; }; static void save_nofork_data(struct nofork_save_area *save) { memcpy(&save->die_jmp, &die_jmp, sizeof(die_jmp)); + save->die_func = die_func; save->applet_name = applet_name; - save->xfunc_error_retval = xfunc_error_retval; save->option_mask32 = option_mask32; - save->die_sleep = die_sleep; + save->xfunc_error_retval = xfunc_error_retval; } static void restore_nofork_data(struct nofork_save_area *save) { memcpy(&die_jmp, &save->die_jmp, sizeof(die_jmp)); + die_func = save->die_func; applet_name = save->applet_name; - xfunc_error_retval = save->xfunc_error_retval; option_mask32 = save->option_mask32; - die_sleep = save->die_sleep; + xfunc_error_retval = save->xfunc_error_retval; } int FAST_FUNC run_nofork_applet(int applet_no, char **argv) @@ -133,11 +149,8 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv) while (argv[argc]) argc++; - /* Special flag for xfunc_die(). If xfunc will "die" - * in NOFORK applet, xfunc_die() sees negative - * die_sleep and longjmp here instead. */ - die_sleep = -1; - + /* If xfunc "dies" in NOFORK applet, die_func longjmp's here instead */ + die_func = jump; rc = setjmp(die_jmp); if (!rc) { /* Some callers (xargs) @@ -146,10 +159,8 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv) memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0])); /* Finally we can call NOFORK applet's main() */ rc = applet_main[applet_no](argc, tmp_argv); - } else { /* xfunc died in NOFORK applet */ - /* in case they meant to return 0... */ - if (rc == -2222) - rc = 0; + } else { + /* xfunc died in NOFORK applet */ } /* Restoring some globals */ |