]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
Bash-5.0 patch 5: prevent optimizing forks away too aggressively
authorChet Ramey <chet.ramey@case.edu>
Sat, 20 Apr 2019 18:25:52 +0000 (14:25 -0400)
committerChet Ramey <chet.ramey@case.edu>
Sat, 20 Apr 2019 18:25:52 +0000 (14:25 -0400)
builtins/evalstring.c
command.h
execute_cmd.c
patchlevel.h

index 1496eeec2c01e7fa01c14bf4f965e0a20a964268..cadc9bc0653520fbbf3f6ef9b3d77a45b668065b 100644 (file)
@@ -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 ). */
index 32495162af65d1eb3af0944c6b193b070646cba2..b9e9b6693b0b19edcb859465f89a96e5243cd3b3 100644 (file)
--- a/command.h
+++ b/command.h
@@ -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 {
index 8b3c83aa8aedb92353fd3fb93b56143238ca584c..f1d74bfecf0a4afcc2c06fe5f6bd8e9c816703e7 100644 (file)
@@ -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;
index c059f0bd769b78ddf0bf0c5c1394e2ec8858d067..1bc098b84f43c98059b287b9d16049ec84a76278 100644 (file)
@@ -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_ */