tar: conditionally don't wait for vforked child to exec, as it always
works right on Linux, and anyway mayresult only on less-than-clear error message only, it will not cause tar to misbehave. function old new delta open_transformer 98 80 -18 writeTarFile 714 547 -167 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-185) Total: -185 bytes text data bss dec hex filename 770651 1051 10764 782466 bf082 busybox_old 770463 1051 10764 782278 befc6 busybox_unstripped
This commit is contained in:
parent
f0000653e9
commit
7e0fbf9c26
@ -25,8 +25,10 @@ int open_transformer(int src_fd,
|
|||||||
close(fd_pipe[0]); /* We don't wan't to read from the parent */
|
close(fd_pipe[0]); /* We don't wan't to read from the parent */
|
||||||
// FIXME: error check?
|
// FIXME: error check?
|
||||||
transformer(src_fd, fd_pipe[1]);
|
transformer(src_fd, fd_pipe[1]);
|
||||||
|
if (ENABLE_FEATURE_CLEAN_UP) {
|
||||||
close(fd_pipe[1]); /* Send EOF */
|
close(fd_pipe[1]); /* Send EOF */
|
||||||
close(src_fd);
|
close(src_fd);
|
||||||
|
}
|
||||||
exit(0);
|
exit(0);
|
||||||
/* notreached */
|
/* notreached */
|
||||||
}
|
}
|
||||||
|
@ -504,13 +504,21 @@ static int writeTarFile(const int tar_fd, const int verboseFlag,
|
|||||||
bb_perror_msg_and_die("cannot stat tar file");
|
bb_perror_msg_and_die("cannot stat tar file");
|
||||||
|
|
||||||
if ((ENABLE_FEATURE_TAR_GZIP || ENABLE_FEATURE_TAR_BZIP2) && gzip) {
|
if ((ENABLE_FEATURE_TAR_GZIP || ENABLE_FEATURE_TAR_BZIP2) && gzip) {
|
||||||
int gzipDataPipe[2] = { -1, -1 };
|
// On Linux, vfork never unpauses parent early, although standard
|
||||||
int gzipStatusPipe[2] = { -1, -1 };
|
// allows for that. Do we want to waste bytes checking for it?
|
||||||
|
#define WAIT_FOR_CHILD 0
|
||||||
|
|
||||||
volatile int vfork_exec_errno = 0;
|
volatile int vfork_exec_errno = 0;
|
||||||
|
#if WAIT_FOR_CHILD
|
||||||
|
struct { int rd; int wr; } gzipStatusPipe;
|
||||||
|
#endif
|
||||||
|
struct { int rd; int wr; } gzipDataPipe;
|
||||||
const char *zip_exec = (gzip == 1) ? "gzip" : "bzip2";
|
const char *zip_exec = (gzip == 1) ? "gzip" : "bzip2";
|
||||||
|
|
||||||
xpipe(gzipDataPipe);
|
xpipe(&gzipDataPipe.rd);
|
||||||
xpipe(gzipStatusPipe);
|
#if WAIT_FOR_CHILD
|
||||||
|
xpipe(&gzipStatusPipe.rd);
|
||||||
|
#endif
|
||||||
|
|
||||||
signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */
|
signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */
|
||||||
|
|
||||||
@ -522,41 +530,45 @@ static int writeTarFile(const int tar_fd, const int verboseFlag,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
gzipPid = vfork();
|
gzipPid = vfork();
|
||||||
|
if (gzipPid < 0)
|
||||||
|
bb_perror_msg_and_die("vfork gzip");
|
||||||
|
|
||||||
if (gzipPid == 0) {
|
if (gzipPid == 0) {
|
||||||
dup2(gzipDataPipe[0], 0);
|
/* child */
|
||||||
close(gzipDataPipe[1]);
|
xmove_fd(tbInfo.tarFd, 1);
|
||||||
|
xmove_fd(gzipDataPipe.rd, 0);
|
||||||
dup2(tbInfo.tarFd, 1);
|
close(gzipDataPipe.wr);
|
||||||
|
#if WAIT_FOR_CHILD
|
||||||
close(gzipStatusPipe[0]);
|
close(gzipStatusPipe.rd);
|
||||||
fcntl(gzipStatusPipe[1], F_SETFD, FD_CLOEXEC); /* close on exec shows success */
|
fcntl(gzipStatusPipe.wr, F_SETFD, FD_CLOEXEC);
|
||||||
|
#endif
|
||||||
|
/* exec gzip/bzip2 program/applet */
|
||||||
BB_EXECLP(zip_exec, zip_exec, "-f", NULL);
|
BB_EXECLP(zip_exec, zip_exec, "-f", NULL);
|
||||||
vfork_exec_errno = errno;
|
vfork_exec_errno = errno;
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
close(gzipStatusPipe[1]);
|
/* parent */
|
||||||
exit(-1);
|
xmove_fd(gzipDataPipe.wr, tbInfo.tarFd);
|
||||||
} else if (gzipPid > 0) {
|
close(gzipDataPipe.rd);
|
||||||
close(gzipDataPipe[0]);
|
#if WAIT_FOR_CHILD
|
||||||
close(gzipStatusPipe[1]);
|
close(gzipStatusPipe.wr);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
char buf;
|
char buf;
|
||||||
|
int n;
|
||||||
|
|
||||||
int n = full_read(gzipStatusPipe[0], &buf, 1);
|
/* Wait until child execs (or fails to) */
|
||||||
|
n = full_read(gzipStatusPipe.rd, &buf, 1);
|
||||||
|
if ((n < 0) && (/*errno == EAGAIN ||*/ errno == EINTR))
|
||||||
|
continue; /* try it again */
|
||||||
|
|
||||||
if (n == 0 && vfork_exec_errno != 0) {
|
}
|
||||||
|
close(gzipStatusPipe.rd);
|
||||||
|
#endif
|
||||||
|
if (vfork_exec_errno) {
|
||||||
errno = vfork_exec_errno;
|
errno = vfork_exec_errno;
|
||||||
bb_perror_msg_and_die("cannot exec %s", zip_exec);
|
bb_perror_msg_and_die("cannot exec %s", zip_exec);
|
||||||
} else if ((n < 0) && (errno == EAGAIN || errno == EINTR))
|
|
||||||
continue; /* try it again */
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
close(gzipStatusPipe[0]);
|
|
||||||
|
|
||||||
tbInfo.tarFd = gzipDataPipe[1];
|
|
||||||
} else bb_perror_msg_and_die("vfork gzip");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tbInfo.excludeList = exclude;
|
tbInfo.excludeList = exclude;
|
||||||
|
@ -512,6 +512,9 @@ int execable_file(const char *name);
|
|||||||
char *find_execable(const char *filename);
|
char *find_execable(const char *filename);
|
||||||
int exists_execable(const char *filename);
|
int exists_execable(const char *filename);
|
||||||
|
|
||||||
|
/* BB_EXECxx always execs (it's not doing NOFORK/NOEXEC stuff),
|
||||||
|
* but it may exec busybox and call applet instead of searching PATH.
|
||||||
|
*/
|
||||||
#if ENABLE_FEATURE_PREFER_APPLETS
|
#if ENABLE_FEATURE_PREFER_APPLETS
|
||||||
int bb_execvp(const char *file, char *const argv[]);
|
int bb_execvp(const char *file, char *const argv[]);
|
||||||
#define BB_EXECVP(prog,cmd) bb_execvp(prog,cmd)
|
#define BB_EXECVP(prog,cmd) bb_execvp(prog,cmd)
|
||||||
|
Loading…
Reference in New Issue
Block a user