remove global "jmp_buf die_jmp" from !FEATURE_PREFER_APPLETS builds
authorDenys Vlasenko <vda.linux@googlemail.com>
Fri, 9 Oct 2015 14:42:57 +0000 (16:42 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Fri, 9 Oct 2015 14:42:57 +0000 (16:42 +0200)
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>
include/libbb.h
init/init.c
libbb/fflush_stdout_and_exit.c
libbb/vfork_daemon_rexec.c
libbb/xfunc_die.c
loginutils/getty.c
shell/hush.c

index d79843a2d72d9c27cb7d386ac608e297dc28c10a..2f24ecbc334ccd4aa04298c324a144b92c9005ca 100644 (file)
@@ -1127,9 +1127,8 @@ enum {
 extern const char *msg_eol;
 extern smallint syslog_level;
 extern smallint logmode;
-extern int die_sleep;
 extern uint8_t xfunc_error_retval;
-extern jmp_buf die_jmp;
+extern void (*die_func)(void);
 extern void xfunc_die(void) NORETURN FAST_FUNC;
 extern void bb_show_usage(void) NORETURN FAST_FUNC;
 extern void bb_error_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))) FAST_FUNC;
index b2fe85635eb2275569edecc1187b81a63576cfb5..80c5d0f74cb8fac6b1de810d9bf4897433a3e12f 100644 (file)
@@ -1015,6 +1015,11 @@ void handle_sigsegv(int sig, siginfo_t *info, void *ucontext)
 }
 #endif
 
+static void sleep_much(void)
+{
+        sleep(30 * 24*60*60);
+}
+
 int init_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int init_main(int argc UNUSED_PARAM, char **argv)
 {
@@ -1051,12 +1056,12 @@ int init_main(int argc UNUSED_PARAM, char **argv)
 
        /* If, say, xmalloc would ever die, we don't want to oops kernel
         * by exiting.
-        * NB: we set die_sleep *after* PID 1 check and bb_show_usage.
+        * NB: we set die_func *after* PID 1 check and bb_show_usage.
         * Otherwise, for example, "init u" ("please rexec yourself"
         * command for sysvinit) will show help text (which isn't too bad),
         * *and sleep forever* (which is bad!)
         */
-       die_sleep = 30 * 24*60*60;
+       die_func = sleep_much;
 
        /* Figure out where the default console should be */
        console_init();
index 9ad5dbf968f536147221edde0081f9a38949dbec..b4bed865f07836cf8015d58095ae96ce803d571a 100644 (file)
 
 void FAST_FUNC fflush_stdout_and_exit(int retval)
 {
+       xfunc_error_retval = retval;
        if (fflush(stdout))
                bb_perror_msg_and_die(bb_msg_standard_output);
-
-       if (ENABLE_FEATURE_PREFER_APPLETS && die_sleep < 0) {
-               /* We are in NOFORK applet. Do not exit() directly,
-                * but use xfunc_die() */
-               xfunc_error_retval = retval;
-               xfunc_die();
-       }
-
-       exit(retval);
+       /* In case we are in NOFORK applet. Do not exit() directly,
+        * but use xfunc_die() */
+       xfunc_die();
 }
index ed1f86f0c5748383ba63b9c95253de72532e631e..d6ca7b263acca7f9d21dd1bcd000e4281e6bd3be 100644 (file)
@@ -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 */
index 204e5e49da5e1e5174752c79da0cd351737c4d1a..73f7998e583f28bb2c70618314f25c5c626d6d41 100644 (file)
@@ -7,34 +7,16 @@
  * Licensed under GPLv2, see file LICENSE in this source tree.
  */
 
-/* Keeping it separate allows to NOT suck in stdio for VERY small applets.
+/* Keeping it separate allows to NOT pull in stdio for VERY small applets.
  * Try building busybox with only "true" enabled... */
 
 #include "libbb.h"
 
-int die_sleep;
-#if ENABLE_FEATURE_PREFER_APPLETS || ENABLE_HUSH
-jmp_buf die_jmp;
-#endif
+void (*die_func)(void);
 
 void FAST_FUNC xfunc_die(void)
 {
-       if (die_sleep) {
-               if ((ENABLE_FEATURE_PREFER_APPLETS || ENABLE_HUSH)
-                && die_sleep < 0
-               ) {
-                       /* 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!
-                        */
-                       /* -2222 means "zero" (longjmp can't pass 0)
-                        * run_nofork_applet() catches -2222. */
-                       longjmp(die_jmp, xfunc_error_retval ? xfunc_error_retval : -2222);
-               }
-               sleep(die_sleep);
-       }
+       if (die_func)
+               die_func();
        exit(xfunc_error_retval);
 }
index 174542841925f0d9d98426a53f52c5d31db448e7..762d5c7733d00cd1f1ea06e283526dcc1643fdbd 100644 (file)
@@ -520,6 +520,11 @@ static void alarm_handler(int sig UNUSED_PARAM)
        _exit(EXIT_SUCCESS);
 }
 
+static void sleep10(void)
+{
+       sleep(10);
+}
+
 int getty_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int getty_main(int argc UNUSED_PARAM, char **argv)
 {
@@ -599,7 +604,7 @@ int getty_main(int argc UNUSED_PARAM, char **argv)
                close(n--);
 
        /* Logging. We want special flavor of error_msg_and_die */
-       die_sleep = 10;
+       die_func = sleep10;
        msg_eol = "\r\n";
        /* most likely will internally use fd #3 in CLOEXEC mode: */
        openlog(applet_name, LOG_PID, LOG_AUTH);
index f085ed3ebdbf0e301b071e2618ce785bfadbbd87..0d107715fed69aa888d9829bb73165dd5510dc8a 100644 (file)
@@ -1479,10 +1479,11 @@ static sighandler_t install_sighandler(int sig, sighandler_t handler)
 
 #if ENABLE_HUSH_JOB
 
+static void xfunc_has_died(void);
 /* After [v]fork, in child: do not restore tty pgrp on xfunc death */
-# define disable_restore_tty_pgrp_on_exit() (die_sleep = 0)
+# define disable_restore_tty_pgrp_on_exit() (die_func = NULL)
 /* After [v]fork, in parent: restore tty pgrp on xfunc death */
-# define enable_restore_tty_pgrp_on_exit()  (die_sleep = -1)
+# define enable_restore_tty_pgrp_on_exit()  (die_func = xfunc_has_died)
 
 /* Restores tty foreground process group, and exits.
  * May be called as signal handler for fatal signal
@@ -1587,6 +1588,15 @@ static void hush_exit(int exitcode)
 #endif
 }
 
+static void xfunc_has_died(void) NORETURN;
+static void xfunc_has_died(void)
+{
+       /* xfunc has failed! die die die */
+       /* no EXIT traps, this is an escape hatch! */
+       G.exiting = 1;
+       hush_exit(xfunc_error_retval);
+}
+
 
 //TODO: return a mask of ALL handled sigs?
 static int check_and_run_traps(void)
@@ -7866,12 +7876,7 @@ int hush_main(int argc, char **argv)
        /* Initialize some more globals to non-zero values */
        cmdedit_update_prompt();
 
-       if (setjmp(die_jmp)) {
-               /* xfunc has failed! die die die */
-               /* no EXIT traps, this is an escape hatch! */
-               G.exiting = 1;
-               hush_exit(xfunc_error_retval);
-       }
+       die_func = xfunc_has_died;
 
        /* Shell is non-interactive at first. We need to call
         * install_special_sighandlers() if we are going to execute "sh <script>",
@@ -8129,9 +8134,7 @@ int hush_main(int argc, char **argv)
                        /* Grab control of the terminal */
                        tcsetpgrp(G_interactive_fd, getpid());
                }
-               /* -1 is special - makes xfuncs longjmp, not exit
-                * (we reset die_sleep = 0 whereever we [v]fork) */
-               enable_restore_tty_pgrp_on_exit(); /* sets die_sleep = -1 */
+               enable_restore_tty_pgrp_on_exit();
 
 # if ENABLE_HUSH_SAVEHISTORY && MAX_HISTORY > 0
                {