aboutsummaryrefslogtreecommitdiff
path: root/libbb/vfork_daemon_rexec.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2015-10-09 16:42:57 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2015-10-09 16:42:57 +0200
commit550bf5b4a418378cd8f9fbbf5252fe57acdacb5a (patch)
tree7ed13e04cf415be6830363953220d7cffd4580b8 /libbb/vfork_daemon_rexec.c
parent4cd99e7c6c1af77721b890ed5ae26d747796c4bd (diff)
downloadbusybox-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.c39
1 files changed, 25 insertions, 14 deletions
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c
index ed1f86f0c..d6ca7b263 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 */