> > (trap "echo WORKS" EXIT; touch x) > > (trap "echo WORKS" EXIT && touch x) > > bash -c 'trap "echo WORKS" EXIT; true' > > bash -c 'trap "echo WORKS" EXIT; false' > > bash -c 'trap "echo WORKS" EXIT; touch x && a' > > bash -c 'trap "echo WORKS" EXIT; touch x; a' > > > > They all produce the output "WORKS" as the trap runs on exit. (Where "a" > > is not a command or in the path and produces an error.) > > > > Now consider this command: > > > > bash -c 'trap "echo WORKS" EXIT && touch x' > > > > On newer versions of bash, it produces no output. Substituting different > > commands in the trap or tracing it seems to indicate that the trap never > > runs. > > It's a case of bash being too aggressive optimizing the last command in > the AND_OR list. Here's a patch that disables that optimization attempt > while I look at alternatives.
Here's a better patch that doesn't just disable the fork optimization. Please let me know how it works in your testing. Chet
*** ../bash-5.0-patched/command.h 2018-07-20 21:16:31.000000000 -0400 --- command.h 2019-02-20 11:09:36.000000000 -0500 *************** *** 187,190 **** --- 188,192 ---- #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. */ *** ../bash-5.0-patched/builtins/evalstring.c 2018-12-26 11:19:21.000000000 -0500 --- builtins/evalstring.c 2019-01-29 14:15:19.000000000 -0500 *************** *** 101,104 **** --- 101,113 ---- } + 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) *************** *** 106,110 **** { if (command->type == cm_connection && ! (command->value.Connection->connector == AND_AND || command->value.Connection->connector == OR_OR) && should_suppress_fork (command->value.Connection->second)) { --- 115,120 ---- { if (command->type == cm_connection && ! (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)) { *************** *** 413,418 **** command->value.Simple->flags |= CMD_NO_FORK; } ! else if (command->type == cm_connection) ! optimize_fork (command); #endif /* ONESHOT */ --- 423,438 ---- command->value.Simple->flags |= CMD_NO_FORK; } ! ! /* 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 */ *** ../bash-5.0-patched/execute_cmd.c 2018-12-05 09:05:14.000000000 -0500 --- execute_cmd.c 2019-01-25 15:59:00.000000000 -0500 *************** *** 2768,2771 **** --- 2768,2773 ---- (exec_result != EXECUTION_SUCCESS))) { + optimize_fork (command); + second = command->value.Connection->second; if (ignore_return && second)
``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRU c...@case.edu http://tiswww.cwru.edu/~chet/