diff options
author | Chet Ramey <chet.ramey@case.edu> | 2019-04-20 14:25:52 -0400 |
---|---|---|
committer | Chet Ramey <chet.ramey@case.edu> | 2019-04-20 14:25:52 -0400 |
commit | 41f5420db7a911fb0833be693205f4db41f05434 (patch) | |
tree | f31fd0738f087fda8e3d890004a37e8e5c451b30 | |
parent | 16c907aa3bb427618733e5a6f2f4e2fc5a3488d3 (diff) | |
download | bash-41f5420db7a911fb0833be693205f4db41f05434.tar.gz |
Bash-5.0 patch 5: prevent optimizing forks away too aggressively
-rw-r--r-- | builtins/evalstring.c | 26 | ||||
-rw-r--r-- | command.h | 1 | ||||
-rw-r--r-- | execute_cmd.c | 2 | ||||
-rw-r--r-- | patchlevel.h | 2 |
4 files changed, 27 insertions, 4 deletions
diff --git a/builtins/evalstring.c b/builtins/evalstring.c index 1496eeec..cadc9bc0 100644 --- a/builtins/evalstring.c +++ b/builtins/evalstring.c @@ -100,12 +100,22 @@ should_suppress_fork (command) ((command->flags & CMD_INVERT_RETURN) == 0)); } +int +can_optimize_connection (command) + COMMAND *command; +{ + return (*bash_input.location.string == '\0' && + (command->value.Connection->connector == AND_AND || command->value.Connection->connector == OR_OR || command->value.Connection->connector == ';') && + command->value.Connection->second->type == cm_simple); +} + void optimize_fork (command) COMMAND *command; { if (command->type == cm_connection && - (command->value.Connection->connector == AND_AND || command->value.Connection->connector == OR_OR) && + (command->value.Connection->connector == AND_AND || command->value.Connection->connector == OR_OR || command->value.Connection->connector == ';') && + (command->value.Connection->second->flags & CMD_TRY_OPTIMIZING) && should_suppress_fork (command->value.Connection->second)) { command->value.Connection->second->flags |= CMD_NO_FORK; @@ -412,8 +422,18 @@ parse_and_execute (string, from_file, flags) command->flags |= CMD_NO_FORK; command->value.Simple->flags |= CMD_NO_FORK; } - else if (command->type == cm_connection) - optimize_fork (command); + + /* Can't optimize forks out here execept for simple commands. + This knows that the parser sets up commands as left-side heavy + (&& and || are left-associative) and after the single parse, + if we are at the end of the command string, the last in a + series of connection commands is + command->value.Connection->second. */ + else if (command->type == cm_connection && can_optimize_connection (command)) + { + command->value.Connection->second->flags |= CMD_TRY_OPTIMIZING; + command->value.Connection->second->value.Simple->flags |= CMD_TRY_OPTIMIZING; + } #endif /* ONESHOT */ /* See if this is a candidate for $( <file ). */ @@ -186,6 +186,7 @@ typedef struct element { #define CMD_COPROC_SUBSHELL 0x1000 #define CMD_LASTPIPE 0x2000 #define CMD_STDPATH 0x4000 /* use standard path for command lookup */ +#define CMD_TRY_OPTIMIZING 0x8000 /* try to optimize this simple command */ /* What a command looks like. */ typedef struct command { diff --git a/execute_cmd.c b/execute_cmd.c index 8b3c83aa..f1d74bfe 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -2767,6 +2767,8 @@ execute_connection (command, asynchronous, pipe_in, pipe_out, fds_to_close) ((command->value.Connection->connector == OR_OR) && (exec_result != EXECUTION_SUCCESS))) { + optimize_fork (command); + second = command->value.Connection->second; if (ignore_return && second) second->flags |= CMD_IGNORE_RETURN; diff --git a/patchlevel.h b/patchlevel.h index c059f0bd..1bc098b8 100644 --- a/patchlevel.h +++ b/patchlevel.h @@ -25,6 +25,6 @@ regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh looks for to find the patch level (for the sccs version string). */ -#define PATCHLEVEL 4 +#define PATCHLEVEL 5 #endif /* _PATCHLEVEL_H_ */ |