On Thu, Dec 29, 2016 at 9:39 PM, Eduardo Bustamante <dual...@gmail.com> wrote:
> I'm adding the bug-bash list, since I think this is actually a bug in
> the parse_comsub function, or maybe in execute_command_internal. I
> haven't been able to figure it out yet. What I do know is that these
> two should behave the same:
I'm not sure what was I thinking, but these are of course very
different things (comsub and subshell) :-)

I still think this is a bug, because line number information
(line_number, line_number_for_err_trap and the line attribute in the
different command structures) is handled inconsistently.

The problem is that line information is lost when executing the body
of a function, so what bash does is to store line number information
in the command structures, so that it's able to correctly report to
the ERR trap when it is triggered. But for some reason this is not
handled in a consistent manner for different types of commands, so the
following fail:

- subshells e.g. (exit 17)
- arithmetic commands e.g. (( 0 ))
- conditional commands, e.g. [[ a = b ]]

I don't think this applies for the following types: if, case, for,
arith-for, but I may be wrong.

The attached err_lineno patch is a proposed fix. The reported line
number will be the closing line in the case of a subshell and the
other multi-line constructs. This seems to match the current behavior
when executing outside a function.
diff --git a/command.h b/command.h
index 3bf479a..678df79 100644
--- a/command.h
+++ b/command.h
@@ -353,6 +353,7 @@ typedef struct group_com {
 
 typedef struct subshell_com {
   int flags;
+  int line;
   COMMAND *command;
 } SUBSHELL_COM;
 
diff --git a/copy_cmd.c b/copy_cmd.c
index 826e0c3..ec71b70 100644
--- a/copy_cmd.c
+++ b/copy_cmd.c
@@ -221,6 +221,7 @@ copy_subshell_command (com)
   new_subshell = (SUBSHELL_COM *)xmalloc (sizeof (SUBSHELL_COM));
   new_subshell->command = copy_command (com->command);
   new_subshell->flags = com->flags;
+  new_subshell->line= com->line;
   return (new_subshell);
 }
 
diff --git a/execute_cmd.c b/execute_cmd.c
index 2fff093..29c3e2f 100644
--- a/execute_cmd.c
+++ b/execute_cmd.c
@@ -606,7 +606,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
 
       /* Fork a subshell, turn off the subshell bit, turn off job
 	 control and call execute_command () on the command again. */
-      line_number_for_err_trap = line_number;	/* XXX - save value? */
+      line_number_for_err_trap = line_number = command->value.Subshell->line;
       tcmd = make_command_string (command);
       paren_pid = make_child (p = savestring (tcmd), asynchronous);
 
@@ -3600,7 +3600,7 @@ execute_arith_command (arith_command)
 
   save_line_number = line_number;
   this_command_name = "((";	/* )) */
-  line_number = arith_command->line;
+  line_number_for_err_trap = line_number = arith_command->line;
   /* If we're in a function, update the line number information. */
   if (variable_context && interactive_shell)
     {
@@ -3801,7 +3801,7 @@ execute_cond_command (cond_command)
   save_line_number = line_number;
 
   this_command_name = "[[";
-  line_number = cond_command->line;
+  line_number_for_err_trap = line_number = cond_command->line;
   /* If we're in a function, update the line number information. */
   if (variable_context && interactive_shell)
     {
diff --git a/make_cmd.c b/make_cmd.c
index b42e9ff..6067ecb 100644
--- a/make_cmd.c
+++ b/make_cmd.c
@@ -822,6 +822,7 @@ make_subshell_command (command)
   temp = (SUBSHELL_COM *)xmalloc (sizeof (SUBSHELL_COM));
   temp->command = command;
   temp->flags = CMD_WANT_SUBSHELL;
+  temp->line = line_number;
   return (make_command (cm_subshell, (SIMPLE_COM *)temp));
 }
 

Reply via email to