hush/libbb/xfunc.die.c
Stephen Heumann c37475dcbc Change vfork_and_run implementation to inspect the kernel's process tables to determine whether the child has really exec'd or exited.
This should avoid strange behavior due to races when the parent has resumed but the child is still running the exec* code in libc, which mainly manifests itself when running at low speed.

We also change to signaling the child's completion with SIGALRM, and setting an extra alarm in the parent in case the child doesn't actually do it.
2014-11-10 16:08:24 -06:00

46 lines
1.1 KiB
C

/* vi: set sw=4 ts=4: */
/*
* Utility routines.
*
* Copyright (C) 2008 by Denys Vlasenko <vda.linux@googlemail.com>
*
* Licensed under GPLv2, see file LICENSE in this source tree.
*/
/* Keeping it separate allows to NOT suck 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 FAST_FUNC xfunc_die(void)
{
int forked;
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 (!is_forked_child())
exit(xfunc_error_retval);
else
_exit(xfunc_error_retval);
}