remove global "jmp_buf die_jmp" from !FEATURE_PREFER_APPLETS builds
No binary (build failed)
—
(log yok)
| @@ -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; | |
| @@ -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(); | |
| @@ -15,15 +15,10 @@ | |
| 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(); |
| } | |
| @@ -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 */ | |
| @@ -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); | |
| } | |
| @@ -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); | |
| @@ -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 | |
| { | |