Make internal_vproblem always work
authorGary Benson <gbenson@redhat.com>
Tue, 5 Aug 2014 10:42:21 +0000 (11:42 +0100)
committerGary Benson <gbenson@redhat.com>
Fri, 29 Aug 2014 09:11:59 +0000 (10:11 +0100)
internal_vproblem can be called (via malloc_failure) from almost the
first line of captured_main, but it will crash if called before the
first call to set_width.  This commit makes internal_vproblem work
at any time.

There are two parts to this.  If called before gdb_stderr is set up,
internal_vproblem will fall back to printing the message on regular
stderr and aborting.  If called after gdb_stderr is set up but before
filtered printing is set up, internal_vproblem will operate as usual
except that it can not query whether to quit and/or dump core so it
defaults to doing both.

gdb/ChangeLog:

* utils.h (filtered_printing_initialized): New declaration.
* utils.c (abort_with_message): New function.
(internal_vproblem): Use abort_with_message for first level
recursive internal problems, and if gdb_stderr is not set up.
Protect calls to target_terminal_ours, begin_line and query.

gdb/ChangeLog
gdb/utils.c
gdb/utils.h

index 1da30631751d11d7e889dade712a2cc792eb3d80..1a086ca2103bb403d9d5b01a644aba6affbe7fd4 100644 (file)
@@ -1,3 +1,11 @@
+2014-08-29  Gary Benson  <gbenson@redhat.com>
+
+       * utils.h (filtered_printing_initialized): New declaration.
+       * utils.c (abort_with_message): New function.
+       (internal_vproblem): Use abort_with_message for first level
+       recursive internal problems, and if gdb_stderr is not set up.
+       Protect calls to target_terminal_ours, begin_line and query.
+
 2014-08-28  Doug Evans  <dje@google.com>
 
        * symtab.c (in_prologue): Move definition to better spot.
index 49843731a84c8c414bcffbd8815a1773fc832d9c..5fe9ee6b1fe27fefe50fa7445e57594525e5aebd 100644 (file)
@@ -549,6 +549,19 @@ error_stream (struct ui_file *stream)
   error (("%s"), message);
 }
 
+/* Emit a message and abort.  */
+
+static void ATTRIBUTE_NORETURN
+abort_with_message (const char *msg)
+{
+  if (gdb_stderr == NULL)
+    fputs (msg, stderr);
+  else
+    fputs_unfiltered (msg, gdb_stderr);
+
+  abort ();            /* NOTE: GDB has only three calls to abort().  */
+}
+
 /* Dump core trying to increase the core soft limit to hard limit first.  */
 
 void
@@ -671,8 +684,7 @@ internal_vproblem (struct internal_problem *problem,
        break;
       case 1:
        dejavu = 2;
-       fputs_unfiltered (msg, gdb_stderr);
-       abort ();       /* NOTE: GDB has only three calls to abort().  */
+       abort_with_message (msg);
       default:
        dejavu = 3;
         /* Newer GLIBC versions put the warn_unused_result attribute
@@ -686,10 +698,6 @@ internal_vproblem (struct internal_problem *problem,
       }
   }
 
-  /* Try to get the message out and at the start of a new line.  */
-  target_terminal_ours ();
-  begin_line ();
-
   /* Create a string containing the full error/warning message.  Need
      to call query with this full string, as otherwize the reason
      (error/warning) and question become separated.  Format using a
@@ -707,8 +715,23 @@ internal_vproblem (struct internal_problem *problem,
     make_cleanup (xfree, reason);
   }
 
+  /* Fall back to abort_with_message if gdb_stderr is not set up.  */
+  if (gdb_stderr == NULL)
+    {
+      fputs (reason, stderr);
+      abort_with_message ("\n");
+    }
+
+  /* Try to get the message out and at the start of a new line.  */
+  if (target_supports_terminal_ours ())
+    target_terminal_ours ();
+  if (filtered_printing_initialized ())
+    begin_line ();
+
   /* Emit the message unless query will emit it below.  */
-  if (problem->should_quit != internal_problem_ask || !confirm)
+  if (problem->should_quit != internal_problem_ask
+      || !confirm
+      || !filtered_printing_initialized ())
     fprintf_unfiltered (gdb_stderr, "%s\n", reason);
 
   if (problem->should_quit == internal_problem_ask)
@@ -716,7 +739,7 @@ internal_vproblem (struct internal_problem *problem,
       /* Default (yes/batch case) is to quit GDB.  When in batch mode
         this lessens the likelihood of GDB going into an infinite
         loop.  */
-      if (!confirm)
+      if (!confirm || !filtered_printing_initialized ())
        quit_p = 1;
       else
         quit_p = query (_("%s\nQuit this debugging session? "), reason);
@@ -738,6 +761,8 @@ internal_vproblem (struct internal_problem *problem,
     {
       if (!can_dump_core_warn (LIMIT_MAX, reason))
        dump_core_p = 0;
+      else if (!filtered_printing_initialized ())
+       dump_core_p = 1;
       else
        {
          /* Default (yes/batch case) is to dump core.  This leaves a GDB
@@ -1700,6 +1725,13 @@ init_page_info (void)
   set_width ();
 }
 
+/* Return nonzero if filtered printing is initialized.  */
+int
+filtered_printing_initialized (void)
+{
+  return wrap_buffer != NULL;
+}
+
 /* Helper for make_cleanup_restore_page_info.  */
 
 static void
index 57a1c0ff7792d6057d508caf0cd29143262860bd..62888a70b61ce200ba6d399c26f94b8249228e46 100644 (file)
@@ -244,6 +244,9 @@ extern void fputstrn_filtered (const char *str, int n, int quotr,
 extern void fputstrn_unfiltered (const char *str, int n, int quotr,
                                 struct ui_file * stream);
 
+/* Return nonzero if filtered printing is initialized.  */
+extern int filtered_printing_initialized (void);
+
 /* Display the host ADDR on STREAM formatted as ``0x%x''.  */
 extern void gdb_print_host_address (const void *addr, struct ui_file *stream);