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>
This commit is contained in:
Denys Vlasenko 2015-10-09 16:42:57 +02:00
parent 4cd99e7c6c
commit 550bf5b4a4
7 changed files with 61 additions and 61 deletions

View File

@ -1127,9 +1127,8 @@ enum {
extern const char *msg_eol; extern const char *msg_eol;
extern smallint syslog_level; extern smallint syslog_level;
extern smallint logmode; extern smallint logmode;
extern int die_sleep;
extern uint8_t xfunc_error_retval; 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 xfunc_die(void) NORETURN FAST_FUNC;
extern void bb_show_usage(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; extern void bb_error_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))) FAST_FUNC;

View File

@ -1015,6 +1015,11 @@ void handle_sigsegv(int sig, siginfo_t *info, void *ucontext)
} }
#endif #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, char **argv) MAIN_EXTERNALLY_VISIBLE;
int init_main(int argc UNUSED_PARAM, char **argv) 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 /* If, say, xmalloc would ever die, we don't want to oops kernel
* by exiting. * 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" * Otherwise, for example, "init u" ("please rexec yourself"
* command for sysvinit) will show help text (which isn't too bad), * command for sysvinit) will show help text (which isn't too bad),
* *and sleep forever* (which is 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 */ /* Figure out where the default console should be */
console_init(); console_init();

View File

@ -15,15 +15,10 @@
void FAST_FUNC fflush_stdout_and_exit(int retval) void FAST_FUNC fflush_stdout_and_exit(int retval)
{ {
xfunc_error_retval = retval;
if (fflush(stdout)) if (fflush(stdout))
bb_perror_msg_and_die(bb_msg_standard_output); bb_perror_msg_and_die(bb_msg_standard_output);
/* In case we are in NOFORK applet. Do not exit() directly,
if (ENABLE_FEATURE_PREFER_APPLETS && die_sleep < 0) {
/* We are in NOFORK applet. Do not exit() directly,
* but use xfunc_die() */ * but use xfunc_die() */
xfunc_error_retval = retval;
xfunc_die(); xfunc_die();
}
exit(retval);
} }

View File

@ -69,28 +69,44 @@ pid_t FAST_FUNC xspawn(char **argv)
} }
#if ENABLE_FEATURE_PREFER_APPLETS #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 { struct nofork_save_area {
jmp_buf die_jmp; jmp_buf die_jmp;
void (*die_func)(void);
const char *applet_name; const char *applet_name;
uint32_t option_mask32; uint32_t option_mask32;
int die_sleep;
uint8_t xfunc_error_retval; uint8_t xfunc_error_retval;
}; };
static void save_nofork_data(struct nofork_save_area *save) static void save_nofork_data(struct nofork_save_area *save)
{ {
memcpy(&save->die_jmp, &die_jmp, sizeof(die_jmp)); memcpy(&save->die_jmp, &die_jmp, sizeof(die_jmp));
save->die_func = die_func;
save->applet_name = applet_name; save->applet_name = applet_name;
save->xfunc_error_retval = xfunc_error_retval;
save->option_mask32 = option_mask32; 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) static void restore_nofork_data(struct nofork_save_area *save)
{ {
memcpy(&die_jmp, &save->die_jmp, sizeof(die_jmp)); memcpy(&die_jmp, &save->die_jmp, sizeof(die_jmp));
die_func = save->die_func;
applet_name = save->applet_name; applet_name = save->applet_name;
xfunc_error_retval = save->xfunc_error_retval;
option_mask32 = save->option_mask32; 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) 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]) while (argv[argc])
argc++; argc++;
/* Special flag for xfunc_die(). If xfunc will "die" /* If xfunc "dies" in NOFORK applet, die_func longjmp's here instead */
* in NOFORK applet, xfunc_die() sees negative die_func = jump;
* die_sleep and longjmp here instead. */
die_sleep = -1;
rc = setjmp(die_jmp); rc = setjmp(die_jmp);
if (!rc) { if (!rc) {
/* Some callers (xargs) /* 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])); memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0]));
/* Finally we can call NOFORK applet's main() */ /* Finally we can call NOFORK applet's main() */
rc = applet_main[applet_no](argc, tmp_argv); rc = applet_main[applet_no](argc, tmp_argv);
} else { /* xfunc died in NOFORK applet */ } else {
/* in case they meant to return 0... */ /* xfunc died in NOFORK applet */
if (rc == -2222)
rc = 0;
} }
/* Restoring some globals */ /* Restoring some globals */

View File

@ -7,34 +7,16 @@
* Licensed under GPLv2, see file LICENSE in this source tree. * 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... */ * Try building busybox with only "true" enabled... */
#include "libbb.h" #include "libbb.h"
int die_sleep; void (*die_func)(void);
#if ENABLE_FEATURE_PREFER_APPLETS || ENABLE_HUSH
jmp_buf die_jmp;
#endif
void FAST_FUNC xfunc_die(void) void FAST_FUNC xfunc_die(void)
{ {
if (die_sleep) { if (die_func)
if ((ENABLE_FEATURE_PREFER_APPLETS || ENABLE_HUSH) die_func();
&& 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);
}
exit(xfunc_error_retval); exit(xfunc_error_retval);
} }

View File

@ -520,6 +520,11 @@ static void alarm_handler(int sig UNUSED_PARAM)
_exit(EXIT_SUCCESS); _exit(EXIT_SUCCESS);
} }
static void sleep10(void)
{
sleep(10);
}
int getty_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int getty_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int getty_main(int argc UNUSED_PARAM, char **argv) int getty_main(int argc UNUSED_PARAM, char **argv)
{ {
@ -599,7 +604,7 @@ int getty_main(int argc UNUSED_PARAM, char **argv)
close(n--); close(n--);
/* Logging. We want special flavor of error_msg_and_die */ /* Logging. We want special flavor of error_msg_and_die */
die_sleep = 10; die_func = sleep10;
msg_eol = "\r\n"; msg_eol = "\r\n";
/* most likely will internally use fd #3 in CLOEXEC mode: */ /* most likely will internally use fd #3 in CLOEXEC mode: */
openlog(applet_name, LOG_PID, LOG_AUTH); openlog(applet_name, LOG_PID, LOG_AUTH);

View File

@ -1479,10 +1479,11 @@ static sighandler_t install_sighandler(int sig, sighandler_t handler)
#if ENABLE_HUSH_JOB #if ENABLE_HUSH_JOB
static void xfunc_has_died(void);
/* After [v]fork, in child: do not restore tty pgrp on xfunc death */ /* 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 */ /* 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. /* Restores tty foreground process group, and exits.
* May be called as signal handler for fatal signal * May be called as signal handler for fatal signal
@ -1587,6 +1588,15 @@ static void hush_exit(int exitcode)
#endif #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? //TODO: return a mask of ALL handled sigs?
static int check_and_run_traps(void) 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 */ /* Initialize some more globals to non-zero values */
cmdedit_update_prompt(); cmdedit_update_prompt();
if (setjmp(die_jmp)) { die_func = xfunc_has_died;
/* xfunc has failed! die die die */
/* no EXIT traps, this is an escape hatch! */
G.exiting = 1;
hush_exit(xfunc_error_retval);
}
/* Shell is non-interactive at first. We need to call /* Shell is non-interactive at first. We need to call
* install_special_sighandlers() if we are going to execute "sh <script>", * 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 */ /* Grab control of the terminal */
tcsetpgrp(G_interactive_fd, getpid()); tcsetpgrp(G_interactive_fd, getpid());
} }
/* -1 is special - makes xfuncs longjmp, not exit enable_restore_tty_pgrp_on_exit();
* (we reset die_sleep = 0 whereever we [v]fork) */
enable_restore_tty_pgrp_on_exit(); /* sets die_sleep = -1 */
# if ENABLE_HUSH_SAVEHISTORY && MAX_HISTORY > 0 # if ENABLE_HUSH_SAVEHISTORY && MAX_HISTORY > 0
{ {