|
18 | 18 | # include "prthread.h"
|
19 | 19 | # include "prenv.h"
|
20 | 20 | # include "nsDebug.h"
|
| 21 | +# include "nsString.h" |
21 | 22 | # include "nsXULAppAPI.h"
|
22 | 23 |
|
23 | 24 | # if defined(LINUX)
|
@@ -123,13 +124,40 @@ MOZ_NEVER_INLINE void child_ah_crap_handler(int signum) {
|
123 | 124 | static GLogFunc orig_log_func = nullptr;
|
124 | 125 |
|
125 | 126 | extern "C" {
|
126 |
| -static void my_glib_log_func(const gchar* log_domain, GLogLevelFlags log_level, |
127 |
| - const gchar* message, gpointer user_data); |
| 127 | +static void glib_log_func(const gchar* log_domain, GLogLevelFlags log_level, |
| 128 | + const gchar* message, gpointer user_data); |
128 | 129 | }
|
129 | 130 |
|
130 |
| -/* static */ void my_glib_log_func(const gchar* log_domain, |
131 |
| - GLogLevelFlags log_level, |
132 |
| - const gchar* message, gpointer user_data) { |
| 131 | +// GDK sometimes avoids calling exit handlers, but we still want to know when we |
| 132 | +// crash, see https://gitlab.gnome.org/GNOME/gtk/-/issues/4514 and bug 1743144. |
| 133 | +static bool IsCrashyGtkMessage(const nsACString& aMessage) { |
| 134 | + if (aMessage.EqualsLiteral("Lost connection to Wayland compositor.")) { |
| 135 | + // https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gdk/wayland/gdkeventsource.c#L210 |
| 136 | + return true; |
| 137 | + } |
| 138 | + if (StringBeginsWith(aMessage, "Error flushing display: "_ns)) { |
| 139 | + // https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gdk/wayland/gdkeventsource.c#L68 |
| 140 | + return true; |
| 141 | + } |
| 142 | + if (StringBeginsWith(aMessage, "Error reading events from display: "_ns)) { |
| 143 | + // https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gdk/wayland/gdkeventsource.c#L97 |
| 144 | + return true; |
| 145 | + } |
| 146 | + if (StringBeginsWith(aMessage, "Error "_ns) && |
| 147 | + StringEndsWith(aMessage, " dispatching to Wayland display."_ns)) { |
| 148 | + // https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gdk/wayland/gdkeventsource.c#L205 |
| 149 | + return true; |
| 150 | + } |
| 151 | + return false; |
| 152 | +} |
| 153 | + |
| 154 | +/* static */ void glib_log_func(const gchar* log_domain, |
| 155 | + GLogLevelFlags log_level, const gchar* message, |
| 156 | + gpointer user_data) { |
| 157 | + if (MOZ_UNLIKELY(IsCrashyGtkMessage(nsDependentCString(message)))) { |
| 158 | + MOZ_CRASH_UNSAFE(strdup(message)); |
| 159 | + } |
| 160 | + |
133 | 161 | if (log_level &
|
134 | 162 | (G_LOG_LEVEL_ERROR | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION)) {
|
135 | 163 | NS_DebugBreak(NS_DEBUG_ASSERTION, message, "glib assertion", __FILE__,
|
@@ -291,14 +319,11 @@ void InstallSignalHandlers(const char* aProgname) {
|
291 | 319 | # if defined(MOZ_WIDGET_GTK) && \
|
292 | 320 | (GLIB_MAJOR_VERSION > 2 || \
|
293 | 321 | (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 6))
|
294 |
| - const char* assertString = PR_GetEnv("XPCOM_DEBUG_BREAK"); |
295 |
| - if (assertString && |
296 |
| - (!strcmp(assertString, "suspend") || !strcmp(assertString, "stack") || |
297 |
| - !strcmp(assertString, "abort") || !strcmp(assertString, "trap") || |
298 |
| - !strcmp(assertString, "break"))) { |
299 |
| - // Override the default glib logging function so we get stacks for it too. |
300 |
| - orig_log_func = g_log_set_default_handler(my_glib_log_func, nullptr); |
301 |
| - } |
| 322 | + // Override the default glib logging function to intercept some crashes that |
| 323 | + // are uninterceptable otherwise. |
| 324 | + // Also, when XPCOM_DEBUG_BREAK is set, we can also get stacks for them. |
| 325 | + // so we get stacks for it too. |
| 326 | + orig_log_func = g_log_set_default_handler(glib_log_func, nullptr); |
302 | 327 | # endif
|
303 | 328 | }
|
304 | 329 |
|
|
0 commit comments