Blame SOURCES/gdb-rhbz1491128-batch-mode-exit-status-1of2.patch

689258
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
689258
From: Gary Benson <gbenson@redhat.com>
689258
Date: Wed, 29 Aug 2018 16:11:50 +0100
689258
Subject: gdb-rhbz1491128-batch-mode-exit-status-1of2.patch
689258
689258
;; Fix for 'gdb in batch mode always exit with status 0' (Gary Benson)
689258
;; RHBZ #1491128
689258
689258
Indicate batch mode failures by exiting with nonzero status
689258
689258
This commit causes GDB in batch mode to exit with nonzero status
689258
if the last command to be executed fails.
689258
689258
gdb/ChangeLog:
689258
689258
	PR gdb/13000:
689258
	* gdb/main.c (captured_main_1): Exit with nonzero status
689258
	in batch mode if the last command to be executed failed.
689258
	* NEWS: Mention the above.
689258
689258
gdb/testsuite/ChangeLog:
689258
689258
	PR gdb/13000:
689258
	* gdb.base/batch-exit-status.exp: New file.
689258
	* gdb.base/batch-exit-status.good-commands: Likewise.
689258
	* gdb.base/batch-exit-status.bad-commands: Likewise.
689258
689258
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
689258
--- a/gdb/ChangeLog
689258
+++ b/gdb/ChangeLog
689258
@@ -1,3 +1,10 @@
689258
+2018-08-16  Gary Benson <gbenson@redhat.com>
689258
+
689258
+	PR gdb/13000:
689258
+	* gdb/main.c (captured_main_1): Exit with nonzero status
689258
+	in batch mode if the last command to be executed failed.
689258
+	* NEWS: Mention the above.
689258
+
689258
 2018-08-03  Sergio Durigan Junior  <sergiodj@redhat.com>
689258
 
689258
 	* ser-tcp.c (net_open): Fix thinko when deciding whether to
689258
diff --git a/gdb/NEWS b/gdb/NEWS
689258
--- a/gdb/NEWS
689258
+++ b/gdb/NEWS
689258
@@ -7,6 +7,9 @@
689258
   can be passed using the '[ADDRESS]:PORT' notation, or the regular
689258
   'ADDRESS:PORT' method.
689258
 
689258
+* GDB in batch mode now exits with status 1 if the last command to be
689258
+  executed failed.
689258
+
689258
 *** Changes in GDB 8.2
689258
 
689258
 * The 'set disassembler-options' command now supports specifying options
689258
diff --git a/gdb/main.c b/gdb/main.c
689258
--- a/gdb/main.c
689258
+++ b/gdb/main.c
689258
@@ -518,6 +518,7 @@ captured_main_1 (struct captured_main_args *context, int &python_script)
689258
   int i;
689258
   int save_auto_load;
689258
   struct objfile *objfile;
689258
+  int ret = 1;
689258
 
689258
 #ifdef HAVE_SBRK
689258
   /* Set this before constructing scoped_command_stats.  */
689258
@@ -1051,7 +1052,7 @@ captured_main_1 (struct captured_main_args *context, int &python_script)
689258
      processed; it sets global parameters, which are independent of
689258
      what file you are debugging or what directory you are in.  */
689258
   if (system_gdbinit && !inhibit_gdbinit)
689258
-    catch_command_errors (source_script, system_gdbinit, 0);
689258
+    ret = catch_command_errors (source_script, system_gdbinit, 0);
689258
 
689258
   /* Read and execute $HOME/.gdbinit file, if it exists.  This is done
689258
      *before* all the command line arguments are processed; it sets
689258
@@ -1059,7 +1060,7 @@ captured_main_1 (struct captured_main_args *context, int &python_script)
689258
      debugging or what directory you are in.  */
689258
 
689258
   if (home_gdbinit && !inhibit_gdbinit && !inhibit_home_gdbinit)
689258
-    catch_command_errors (source_script, home_gdbinit, 0);
689258
+    ret = catch_command_errors (source_script, home_gdbinit, 0);
689258
 
689258
   /* Process '-ix' and '-iex' options early.  */
689258
   for (i = 0; i < cmdarg_vec.size (); i++)
689258
@@ -1069,12 +1070,12 @@ captured_main_1 (struct captured_main_args *context, int &python_script)
689258
       switch (cmdarg_p.type)
689258
 	{
689258
 	case CMDARG_INIT_FILE:
689258
-	  catch_command_errors (source_script, cmdarg_p.string,
689258
-				!batch_flag);
689258
+	  ret = catch_command_errors (source_script, cmdarg_p.string,
689258
+				      !batch_flag);
689258
 	  break;
689258
 	case CMDARG_INIT_COMMAND:
689258
-	  catch_command_errors (execute_command, cmdarg_p.string,
689258
-				!batch_flag);
689258
+	  ret = catch_command_errors (execute_command, cmdarg_p.string,
689258
+				      !batch_flag);
689258
 	  break;
689258
 	}
689258
     }
689258
@@ -1082,11 +1083,11 @@ captured_main_1 (struct captured_main_args *context, int &python_script)
689258
   /* Now perform all the actions indicated by the arguments.  */
689258
   if (cdarg != NULL)
689258
     {
689258
-      catch_command_errors (cd_command, cdarg, 0);
689258
+      ret = catch_command_errors (cd_command, cdarg, 0);
689258
     }
689258
 
689258
   for (i = 0; i < dirarg.size (); i++)
689258
-    catch_command_errors (directory_switch, dirarg[i], 0);
689258
+    ret = catch_command_errors (directory_switch, dirarg[i], 0);
689258
 
689258
   /* Skip auto-loading section-specified scripts until we've sourced
689258
      local_gdbinit (which is often used to augment the source search
689258
@@ -1115,19 +1116,19 @@ captured_main_1 (struct captured_main_args *context, int &python_script)
689258
          catch_command_errors returns non-zero on success!
689258
 	 Do not load EXECARG as a symbol file if it has been already processed
689258
 	 as a core file.  */
689258
-      if (catch_command_errors (func, execarg, !batch_flag)
689258
-	  && core_bfd == NULL)
689258
-	catch_command_errors (symbol_file_add_main_adapter, symarg,
689258
-			      !batch_flag);
689258
+      ret = catch_command_errors (func, execarg, !batch_flag);
689258
+      if (ret != 0 && core_bfd == NULL)
689258
+	ret = catch_command_errors (symbol_file_add_main_adapter,
689258
+				    symarg, !batch_flag);
689258
     }
689258
   else
689258
     {
689258
       if (execarg != NULL)
689258
-	catch_command_errors (exec_file_attach, execarg,
689258
-			      !batch_flag);
689258
+	ret = catch_command_errors (exec_file_attach, execarg,
689258
+				    !batch_flag);
689258
       if (symarg != NULL)
689258
-	catch_command_errors (symbol_file_add_main_adapter, symarg,
689258
-			      !batch_flag);
689258
+	ret = catch_command_errors (symbol_file_add_main_adapter,
689258
+				    symarg, !batch_flag);
689258
     }
689258
 
689258
   if (corearg && pidarg)
689258
@@ -1135,9 +1136,14 @@ captured_main_1 (struct captured_main_args *context, int &python_script)
689258
 	     "a core file at the same time."));
689258
 
689258
   if (corearg != NULL)
689258
-    catch_command_errors (core_file_command, corearg, !batch_flag);
689258
+    {
689258
+      ret = catch_command_errors (core_file_command, corearg,
689258
+				  !batch_flag);
689258
+    }
689258
   else if (pidarg != NULL)
689258
-    catch_command_errors (attach_command, pidarg, !batch_flag);
689258
+    {
689258
+      ret = catch_command_errors (attach_command, pidarg, !batch_flag);
689258
+    }
689258
   else if (pid_or_core_arg)
689258
     {
689258
       /* The user specified 'gdb program pid' or gdb program core'.
689258
@@ -1146,17 +1152,23 @@ captured_main_1 (struct captured_main_args *context, int &python_script)
689258
 
689258
       if (isdigit (pid_or_core_arg[0]))
689258
 	{
689258
-	  if (catch_command_errors (attach_command, pid_or_core_arg,
689258
-				    !batch_flag) == 0
689258
+	  ret = catch_command_errors (attach_command, pid_or_core_arg,
689258
+				      !batch_flag);
689258
+	  if (ret == 0
689258
 	      /* attach_command could succeed partially and core_file_command
689258
 		 would try to kill it.  */
689258
 	      && !have_inferiors ())
689258
-	    catch_command_errors (core_file_command, pid_or_core_arg,
689258
-				  !batch_flag);
689258
+	    ret = catch_command_errors (core_file_command,
689258
+					pid_or_core_arg,
689258
+					!batch_flag);
689258
+	}
689258
+      else
689258
+	{
689258
+	  /* Can't be a pid, better be a corefile.  */
689258
+	  ret = catch_command_errors (core_file_command,
689258
+				      pid_or_core_arg,
689258
+				      !batch_flag);
689258
 	}
689258
-      else /* Can't be a pid, better be a corefile.  */
689258
-	catch_command_errors (core_file_command, pid_or_core_arg,
689258
-			      !batch_flag);
689258
     }
689258
 
689258
   if (ttyarg != NULL)
689258
@@ -1180,7 +1192,7 @@ captured_main_1 (struct captured_main_args *context, int &python_script)
689258
 	{
689258
 	  auto_load_local_gdbinit_loaded = 1;
689258
 
689258
-	  catch_command_errors (source_script, local_gdbinit, 0);
689258
+	  ret = catch_command_errors (source_script, local_gdbinit, 0);
689258
 	}
689258
     }
689258
 
689258
@@ -1200,12 +1212,12 @@ captured_main_1 (struct captured_main_args *context, int &python_script)
689258
       switch (cmdarg_p.type)
689258
 	{
689258
 	case CMDARG_FILE:
689258
-	  catch_command_errors (source_script, cmdarg_p.string,
689258
-				!batch_flag);
689258
+	  ret = catch_command_errors (source_script, cmdarg_p.string,
689258
+				      !batch_flag);
689258
 	  break;
689258
 	case CMDARG_COMMAND:
689258
-	  catch_command_errors (execute_command, cmdarg_p.string,
689258
-				!batch_flag);
689258
+	  ret = catch_command_errors (execute_command, cmdarg_p.string,
689258
+				      !batch_flag);
689258
 	  break;
689258
 	}
689258
     }
689258
@@ -1217,8 +1229,11 @@ captured_main_1 (struct captured_main_args *context, int &python_script)
689258
 
689258
   if (batch_flag)
689258
     {
689258
+      int error_status = EXIT_FAILURE;
689258
+      int *exit_arg = ret == 0 ? &error_status : NULL;
689258
+
689258
       /* We have hit the end of the batch file.  */
689258
-      quit_force (NULL, 0);
689258
+      quit_force (exit_arg, 0);
689258
     }
689258
 }
689258
 
689258
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
689258
--- a/gdb/testsuite/ChangeLog
689258
+++ b/gdb/testsuite/ChangeLog
689258
@@ -1,3 +1,10 @@
689258
+2018-08-16  Gary Benson <gbenson@redhat.com>
689258
+
689258
+	PR gdb/13000:
689258
+	* gdb.base/batch-exit-status.exp: New file.
689258
+	* gdb.base/batch-exit-status.good-commands: Likewise.
689258
+	* gdb.base/batch-exit-status.bad-commands: Likewise.
689258
+
689258
 2018-07-11  Sergio Durigan Junior  <sergiodj@redhat.com>
689258
 	    Jan Kratochvil  <jan.kratochvil@redhat.com>
689258
 	    Paul Fertser  <fercerpav@gmail.com>
689258
diff --git a/gdb/testsuite/gdb.base/batch-exit-status.bad-commands b/gdb/testsuite/gdb.base/batch-exit-status.bad-commands
689258
new file mode 100644
689258
--- /dev/null
689258
+++ b/gdb/testsuite/gdb.base/batch-exit-status.bad-commands
689258
@@ -0,0 +1 @@
689258
+bork
689258
diff --git a/gdb/testsuite/gdb.base/batch-exit-status.exp b/gdb/testsuite/gdb.base/batch-exit-status.exp
689258
new file mode 100644
689258
--- /dev/null
689258
+++ b/gdb/testsuite/gdb.base/batch-exit-status.exp
689258
@@ -0,0 +1,63 @@
689258
+# Copyright (C) 2018 Free Software Foundation, Inc.
689258
+
689258
+# This program is free software; you can redistribute it and/or modify
689258
+# it under the terms of the GNU General Public License as published by
689258
+# the Free Software Foundation; either version 3 of the License, or
689258
+# (at your option) any later version.
689258
+#
689258
+# This program is distributed in the hope that it will be useful,
689258
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
689258
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
689258
+# GNU General Public License for more details.
689258
+#
689258
+# You should have received a copy of the GNU General Public License
689258
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
689258
+
689258
+# Check that "gdb -batch" exits with appropriate status.
689258
+
689258
+standard_testfile
689258
+
689258
+set good_commands "$srcdir/$subdir/batch-exit-status.good-commands"
689258
+set bad_commands "$srcdir/$subdir/batch-exit-status.bad-commands"
689258
+
689258
+proc _test_exit_status {expect_status cmdline_opts} {
689258
+    global gdb_spawn_id
689258
+
689258
+    gdb_exit
689258
+    if {[gdb_spawn_with_cmdline_opts $cmdline_opts] != 0} {
689258
+	fail "spawn"
689258
+	return
689258
+    }
689258
+
689258
+    set result [wait -i $gdb_spawn_id]
689258
+    verbose $result
689258
+    gdb_assert { [lindex $result 2] == 0 }
689258
+    set actual_status [lindex $result 3]
689258
+    gdb_assert { $actual_status == $expect_status }
689258
+}
689258
+
689258
+proc test_exit_status {expect_status cmdline_opts} {
689258
+    with_test_prefix $cmdline_opts {
689258
+	_test_exit_status $expect_status $cmdline_opts
689258
+    }
689258
+}
689258
+
689258
+# gdb -batch with nothing to do should exit 0.
689258
+test_exit_status 0 "-batch"
689258
+
689258
+# Bad command-line options should cause exit 1.
689258
+test_exit_status 1 "-batch -jslkflsdjlkfjlksdjf"
689258
+
689258
+# gdb -batch with good commands should exit 0.
689258
+test_exit_status 0 "-batch -ex \"info source\""
689258
+test_exit_status 0 "-batch -x $good_commands"
689258
+
689258
+# gdb -batch with bad commands should exit 1.
689258
+test_exit_status 1 "-batch -ex \"set not-a-thing 4\""
689258
+test_exit_status 1 "-batch -x $bad_commands"
689258
+
689258
+# Success or failure of the last thing determines the exit code.
689258
+test_exit_status 0 "-batch -ex \"set not-a-thing 4\" -x $good_commands"
689258
+test_exit_status 0 "-batch -x $bad_commands -ex \"info source\""
689258
+test_exit_status 1 "-batch -x $good_commands -x $bad_commands"
689258
+test_exit_status 1 "-batch -x $good_commands -ex \"set not-a-thing 4\""
689258
diff --git a/gdb/testsuite/gdb.base/batch-exit-status.good-commands b/gdb/testsuite/gdb.base/batch-exit-status.good-commands
689258
new file mode 100644
689258
--- /dev/null
689258
+++ b/gdb/testsuite/gdb.base/batch-exit-status.good-commands
689258
@@ -0,0 +1 @@
689258
+info mem