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

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