tsan_segfault.patch
application/x-patch
Filename: tsan_segfault.patch
Type: application/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/backend/main/main.c | 1 | 27 |
| src/backend/main/Makefile | 6 | 1 |
| src/backend/main/sanitizer_hook.c | 55 | 0 |
diff --git a/src/backend/main/Makefile b/src/backend/main/Makefile
index 6d34072624b..e49b10fe0c4 100644
--- a/src/backend/main/Makefile
+++ b/src/backend/main/Makefile
@@ -13,6 +13,11 @@ top_builddir = ../../..
include $(top_builddir)/src/Makefile.global
OBJS = \
- main.o
+ main.o \
+ sanitizer_hook.o
+
+# Custom rule to build sanitizer_hook.o without sanitizer instrumentation
+sanitizer_hook.o: sanitizer_hook.c
+ $(CC) $(CPPFLAGS) $(CFLAGS) -fno-sanitize=thread,address,undefined -c -o $@ $<
include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/main/main.c b/src/backend/main/main.c
index 4672aab8378..be61d8db0a6 100644
--- a/src/backend/main/main.c
+++ b/src/backend/main/main.c
@@ -42,7 +42,7 @@
const char *progname;
-static bool reached_main = false;
+bool reached_main = false;
static void startup_hacks(const char *progname);
@@ -415,29 +415,3 @@ check_root(const char *progname)
#endif /* WIN32 */
}
-/*
- * At least on linux, set_ps_display() breaks /proc/$pid/environ. The
- * sanitizer library uses /proc/$pid/environ to implement getenv() as it wants
- * to work independent of libc. When just using undefined and alignment
- * sanitizers, the sanitizer library is only initialized when the first error
- * occurs, by which time we've often already called set_ps_display(),
- * preventing the sanitizer libraries from seeing the options.
- *
- * We can work around that by defining __ubsan_default_options, a weak symbol
- * libsanitizer uses to get defaults from the application, and return
- * getenv("UBSAN_OPTIONS"). But only if main already was reached, so that we
- * don't end up relying on a not-yet-working getenv().
- *
- * As this function won't get called when not running a sanitizer, it doesn't
- * seem necessary to only compile it conditionally.
- */
-const char *__ubsan_default_options(void);
-const char *
-__ubsan_default_options(void)
-{
- /* don't call libc before it's guaranteed to be initialized */
- if (!reached_main)
- return "";
-
- return getenv("UBSAN_OPTIONS");
-}
diff --git a/src/backend/main/sanitizer_hook.c b/src/backend/main/sanitizer_hook.c
new file mode 100644
index 00000000000..61302de0ead
--- /dev/null
+++ b/src/backend/main/sanitizer_hook.c
@@ -0,0 +1,55 @@
+/*-------------------------------------------------------------------------
+ *
+ * sanitizer_hook.c
+ * UBSan options hook to avoid initialization timing issues
+ *
+ * This file provides __ubsan_default_options() without sanitizer
+ * instrumentation to prevent circular dependencies during early
+ * program startup when set_ps_display() breaks /proc/$pid/environ.
+ *
+ * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/backend/main/sanitizer_hook.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include <signal.h>
+#include <stdlib.h>
+
+
+extern bool reached_main;
+
+
+/*
+ * At least on linux, set_ps_display() breaks /proc/$pid/environ. The
+ * sanitizer library uses /proc/$pid/environ to implement getenv() as it wants
+ * to work independent of libc. When just using undefined and alignment
+ * sanitizers, the sanitizer library is only initialized when the first error
+ * occurs, by which time we've often already called set_ps_display(),
+ * preventing the sanitizer libraries from seeing the options.
+ *
+ * We can work around that by defining __ubsan_default_options, a weak symbol
+ * libsanitizer uses to get defaults from the application, and return
+ * getenv("UBSAN_OPTIONS"). But only if main already was reached, so that we
+ * don't end up relying on a not-yet-working getenv().
+ *
+ * As this function won't get called when not running a sanitizer, it doesn't
+ * seem necessary to only compile it conditionally.
+ */
+const char *
+__ubsan_default_options(void)
+{
+ /*
+ * Avoid calling libc until program startup is complete (reached_main).
+ * This prevents sanitizer initialization issues when set_ps_display()
+ * breaks /proc/$pid/environ before sanitizer can read UBSAN_OPTIONS.
+ */
+ if (!reached_main)
+ return "";
+
+ return getenv("UBSAN_OPTIONS");
+}