Fix signal unsafe call inside a signal

Message ID AS8P193MB1285A388BB7894EA516C892EE4EA2@AS8P193MB1285.EURP193.PROD.OUTLOOK.COM
State New
Headers
Series Fix signal unsafe call inside a signal |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gdb_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gdb_check--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 success Testing passed

Commit Message

Bernd Edlinger May 21, 2024, 5 a.m. UTC
  As mentioned in
https://sourceware.org/bugzilla/show_bug.cgi?id=31713#c9
it can easily happen that the signal handler function
handle_fatal_signal() uses various signal unsafe functions.
Fix that by pre-computing the necessary  language specific
strings.
---
 gdb/bt-utils.c  | 13 ++++++++---
 gdb/event-top.c | 58 +++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 61 insertions(+), 10 deletions(-)
  

Comments

Andreas Schwab May 21, 2024, 8:09 a.m. UTC | #1
On Mai 21 2024, Bernd Edlinger wrote:

> diff --git a/gdb/bt-utils.c b/gdb/bt-utils.c
> index f658ce0d4bc..c5d266a0cac 100644
> --- a/gdb/bt-utils.c
> +++ b/gdb/bt-utils.c
> @@ -125,6 +125,8 @@ gdb_internal_backtrace_1 ()
>  
>  /* See the comment on previous version of this function.  */
>  
> +static str_backtrace_incomplete = _("Backtrace might be incomplete.\n");

That calls gettext in a static constructor, which runs before the locale
is set.
  

Patch

diff --git a/gdb/bt-utils.c b/gdb/bt-utils.c
index f658ce0d4bc..c5d266a0cac 100644
--- a/gdb/bt-utils.c
+++ b/gdb/bt-utils.c
@@ -125,6 +125,8 @@  gdb_internal_backtrace_1 ()
 
 /* See the comment on previous version of this function.  */
 
+static str_backtrace_incomplete = _("Backtrace might be incomplete.\n");
+
 static void
 gdb_internal_backtrace_1 ()
 {
@@ -139,7 +141,7 @@  gdb_internal_backtrace_1 ()
 
   backtrace_symbols_fd (buffer, frames, gdb_stderr->fd ());
   if (frames == ARRAY_SIZE (buffer))
-    sig_write (_("Backtrace might be incomplete.\n"));
+    sig_write (str_backtrace_incomplete);
 }
 
 #else
@@ -149,6 +151,11 @@  gdb_internal_backtrace_1 ()
 
 /* See bt-utils.h.  */
 
+#ifdef GDB_PRINT_INTERNAL_BACKTRACE
+static const char *str_backtrace = _("----- Backtrace -----\n");
+static const char *str_backtrace_unavailable = _("Backtrace unavailable\n");
+#endif
+
 void
 gdb_internal_backtrace ()
 {
@@ -161,12 +168,12 @@  gdb_internal_backtrace ()
     gdb_stderr->write_async_safe (msg, strlen (msg));
   };
 
-  sig_write (_("----- Backtrace -----\n"));
+  sig_write (str_backtrace);
 
   if (gdb_stderr->fd () > -1)
     gdb_internal_backtrace_1 ();
   else
-    sig_write (_("Backtrace unavailable\n"));
+    sig_write (str_backtrace_unavailable);
 
   sig_write ("---------------------\n");
 #endif
diff --git a/gdb/event-top.c b/gdb/event-top.c
index 0425bcf9f99..ec75356efc5 100644
--- a/gdb/event-top.c
+++ b/gdb/event-top.c
@@ -891,6 +891,29 @@  unblock_signal (int sig)
   return false;
 }
 
+/* Signal safe language specific strings.  */
+
+#ifdef GDB_PRINT_INTERNAL_BACKTRACE
+static const char *str_fatal_signal = _("Fatal signal: ");
+static const char *str_sigsegv = strsignal(SIGSEGV);
+#ifdef SIGFPE
+static const char *str_sigfpe = strsignal(SIGFPE);
+#endif
+#ifdef SIGBUS
+static const char *str_sigbus = strsignal(SIGBUS);
+#endif
+#ifdef SIGABRT
+static const char *str_sigabrt = strsignal(SIGABRT);
+#endif
+static const char *str_unknown_signal = _("Unknown signal");
+static const char *str_fatal_error_detected_gdb_will_now_terminate =
+		_("A fatal error internal to GDB has been detected, "
+		  "further\ndebugging is not possible.  GDB will now "
+		  "terminate.\n\n");
+static const char *str_this_is_a_bug = _("This is a bug, please report it.");
+static const char *str_for_instructions_see = _("  For instructions, see:\n");
+#endif
+
 /* Called to handle fatal signals.  SIG is the signal number.  */
 
 static void ATTRIBUTE_NORETURN
@@ -909,19 +932,40 @@  handle_fatal_signal (int sig)
   if (bt_on_fatal_signal)
     {
       sig_write ("\n\n");
-      sig_write (_("Fatal signal: "));
-      sig_write (strsignal (sig));
+      sig_write (str_fatal_signal);
+      switch (sig)
+	{
+	case SIGSEGV:
+	  sig_write (str_sigsegv);
+	  break;
+#ifdef SIGFPE
+	case SIGFPE:
+	  sig_write (str_sigfpe);
+	  break;
+#endif
+#ifdef SIGBUS
+	case SIGBUS:
+	  sig_write (str_sigbus);
+	  break;
+#endif
+#ifdef SIGABRT
+	case SIGABRT:
+	  sig_write (str_sigabrt);
+	  break;
+#endif
+	default:
+	  sig_write (str_unknown_signal);
+	  break;
+	}
       sig_write ("\n");
 
       gdb_internal_backtrace ();
 
-      sig_write (_("A fatal error internal to GDB has been detected, "
-		   "further\ndebugging is not possible.  GDB will now "
-		   "terminate.\n\n"));
-      sig_write (_("This is a bug, please report it."));
+      sig_write (str_fatal_error_detected_gdb_will_now_terminate);
+      sig_write (str_this_is_a_bug);
       if (REPORT_BUGS_TO[0] != '\0')
 	{
-	  sig_write (_("  For instructions, see:\n"));
+	  sig_write (str_for_instructions_see);
 	  sig_write (REPORT_BUGS_TO);
 	  sig_write (".");
 	}