aboutsummaryrefslogtreecommitdiff
path: root/shell/ash.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-07-25 20:31:14 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2017-07-25 20:31:14 +0200
commit1e3e2ccd5dd280371c9ca29c0e0304a0d40592af (patch)
tree2a6151351436d06fe61e60b4e71e8deab6378d7c /shell/ash.c
parent86981e3ad2d03e77d1f668ac1603a041be448dae (diff)
downloadbusybox-w32-1e3e2ccd5dd280371c9ca29c0e0304a0d40592af.tar.gz
busybox-w32-1e3e2ccd5dd280371c9ca29c0e0304a0d40592af.tar.bz2
busybox-w32-1e3e2ccd5dd280371c9ca29c0e0304a0d40592af.zip
ash: [SHELL] Optimize dash -c "command" to avoid a fork
Upstream commit: Date: Thu, 7 Jul 2011 13:58:48 +0800 [SHELL] Optimize dash -c "command" to avoid a fork On Sun, Apr 10, 2011 at 07:36:49AM +0000, Jonathan Nieder wrote: > From: Jilles Tjoelker <jilles@stack.nl> > Date: Sat, 13 Jun 2009 16:17:45 -0500 > > This change only affects strings passed to -c, when the -s option is > not used. > > Use the EV_EXIT flag to inform the eval machinery that the string > being passed is the entirety of input. This way, a fork may be > omitted in many special cases. > > If there are empty lines after the last command, the evalcmd will not > see the end early enough and forks will not be omitted. The same thing > seems to happen in bash. > > Example: > sh -c 'ps lT' > No longer shows a shell process waiting for ps to finish. > > [jn: ported from FreeBSD SVN r194128. Bugs are mine.] > > Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Instead of detecting EOF using the input layer, I'm going to use the parser instead. In either case, we always have to read ahead in order to complete the parsing of the previous node. Therefore we always know whether there is more to come, except in the case where we see a newline/semicolon or similar. For the purposes of sh -c, this should be sufficient. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> function old new delta evalstring 190 224 +34 ash_main 1014 1022 +8 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 42/0) Total: 42 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell/ash.c')
-rw-r--r--shell/ash.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 42e14cbc8..c96ec939e 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -6128,7 +6128,9 @@ struct backcmd { /* result of evalbackcmd */
6128}; 6128};
6129 6129
6130/* These forward decls are needed to use "eval" code for backticks handling: */ 6130/* These forward decls are needed to use "eval" code for backticks handling: */
6131#define EV_EXIT 01 /* exit after evaluating tree */ 6131/* flags in argument to evaltree */
6132#define EV_EXIT 01 /* exit after evaluating tree */
6133#define EV_TESTED 02 /* exit status is checked; ignore -e flag */
6132static int evaltree(union node *, int); 6134static int evaltree(union node *, int);
6133 6135
6134static void FAST_FUNC 6136static void FAST_FUNC
@@ -8345,10 +8347,6 @@ commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8345static void *funcblock; /* block to allocate function from */ 8347static void *funcblock; /* block to allocate function from */
8346static char *funcstring_end; /* end of block to allocate strings from */ 8348static char *funcstring_end; /* end of block to allocate strings from */
8347 8349
8348/* flags in argument to evaltree */
8349#define EV_EXIT 01 /* exit after evaluating tree */
8350#define EV_TESTED 02 /* exit status is checked; ignore -e flag */
8351
8352static const uint8_t nodesize[N_NUMBER] ALIGN1 = { 8350static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8353 [NCMD ] = SHELL_ALIGN(sizeof(struct ncmd)), 8351 [NCMD ] = SHELL_ALIGN(sizeof(struct ncmd)),
8354 [NPIPE ] = SHELL_ALIGN(sizeof(struct npipe)), 8352 [NPIPE ] = SHELL_ALIGN(sizeof(struct npipe)),
@@ -12491,6 +12489,12 @@ expandstr(const char *ps)
12491 return stackblock(); 12489 return stackblock();
12492} 12490}
12493 12491
12492static inline int
12493parser_eof(void)
12494{
12495 return tokpushback && lasttoken == TEOF;
12496}
12497
12494/* 12498/*
12495 * Execute a command or commands contained in a string. 12499 * Execute a command or commands contained in a string.
12496 */ 12500 */
@@ -12526,7 +12530,7 @@ evalstring(char *s, int flags)
12526 while ((n = parsecmd(0)) != NODE_EOF) { 12530 while ((n = parsecmd(0)) != NODE_EOF) {
12527 int i; 12531 int i;
12528 12532
12529 i = evaltree(n, flags); 12533 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
12530 if (n) 12534 if (n)
12531 status = i; 12535 status = i;
12532 popstackmark(&smark); 12536 popstackmark(&smark);
@@ -13671,7 +13675,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
13671 // if (!sflag) g_parsefile->pf_fd = -1; 13675 // if (!sflag) g_parsefile->pf_fd = -1;
13672 // ^^ not necessary since now we special-case fd 0 13676 // ^^ not necessary since now we special-case fd 0
13673 // in is_hidden_fd() to not be considered "hidden fd" 13677 // in is_hidden_fd() to not be considered "hidden fd"
13674 evalstring(minusc, 0); 13678 evalstring(minusc, sflag ? 0 : EV_EXIT);
13675 } 13679 }
13676 13680
13677 if (sflag || minusc == NULL) { 13681 if (sflag || minusc == NULL) {