diff options
Diffstat (limited to 'libbb/error_msg_and_die.c')
-rw-r--r-- | libbb/error_msg_and_die.c | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/libbb/error_msg_and_die.c b/libbb/error_msg_and_die.c index 39178a3..4a90493 100644 --- a/libbb/error_msg_and_die.c +++ b/libbb/error_msg_and_die.c @@ -10,14 +10,25 @@ #include "libbb.h" int die_sleep; +#if ENABLE_FEATURE_EXEC_PREFER_APPLETS jmp_buf die_jmp; +#endif -void sleep_and_die(void) +void xfunc_die(void) { if (die_sleep) { - /* Special case: don't die, but jump */ - if (die_sleep < 0) - longjmp(die_jmp, xfunc_error_retval); + if (ENABLE_FEATURE_EXEC_PREFER_APPLETS && 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! + */ + /* -111 means "zero" (longjmp can't pass 0) + * spawn_and_wait() catches -111. */ + longjmp(die_jmp, xfunc_error_retval ? xfunc_error_retval : -111); + } sleep(die_sleep); } exit(xfunc_error_retval); @@ -30,5 +41,5 @@ void bb_error_msg_and_die(const char *s, ...) va_start(p, s); bb_verror_msg(s, p, NULL); va_end(p); - sleep_and_die(); + xfunc_die(); } |