| From: | Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us> |
|---|---|
| To: | Emmanuel Sibi <emmanuelsibi(dot)mec(at)gmail(dot)com> |
| Cc: | pgsql-hackers(at)lists(dot)postgresql(dot)org, Andres Freund <andres(at)anarazel(dot)de> |
| Subject: | Re: [BUG] PostgreSQL crashes with ThreadSanitizer during early initialization |
| Date: | 2025-11-04 22:39:02 |
| Message-ID: | 686137.1762295942@sss.pgh.pa.us |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
Emmanuel Sibi <emmanuelsibi(dot)mec(at)gmail(dot)com> writes:
> Root Cause: The __ubsan_default_options() function in main.c is compiled with TSan instrumentation, creating a circular dependency during sanitizer runtime initialization.
> 1. TSan initialization calls __ubsan_default_options()
> 2. TSan tries to instrument the function
> 3. Instrumentation requires initialized ThreadState
> 4. ThreadState isn't ready because TSan init isn't complete
> 5. Segfault/crash occurs
Hmm. I wonder what is the argument that this is not a bug
of UBSan itself, as it seems to make __ubsan_default_options()
next door to impossible to use safely.
> Proposed Fix: Move __ubsan_default_options() to a separate compilation unit built without sanitizer instrumentation.
I do not love this fix, as it requires exposing reached_main globally,
not to mention getting both of our build systems involved in the hack.
Another problem is that it only defends against a limited set of
sanitizers, though presumably every single one is broken in the same
way (compare [1]).
I tried this as an alternative solution, but it didn't seem to help:
diff --git a/src/backend/main/main.c b/src/backend/main/main.c
index bdcb5e4f261..cc63da97360 100644
--- a/src/backend/main/main.c
+++ b/src/backend/main/main.c
@@ -500,6 +500,12 @@ check_root(const char *progname)
* seem necessary to only compile it conditionally.
*/
const char *__ubsan_default_options(void);
+
+#if __has_attribute(no_sanitize)
+__attribute__((no_sanitize("thread")))
+__attribute__((no_sanitize("address")))
+__attribute__((no_sanitize("undefined")))
+#endif
const char *
__ubsan_default_options(void)
{
This is of course no better on the "limited set of sanitizers"
angle, but it at least keeps the hack localized. Of course,
if it doesn't work that's all moot, but I wonder why not ---
seems like it should have about the same effect as your proposal.
(I did verify that clang complains if I misspell a no_sanitize
argument, so it's not that the syntax has no effect at all.)
Anyway, I think really a bug report to the UBSan folk asking
how one is supposed to use __ubsan_default_options() safely
might be productive.
regards, tom lane
[1] https://www.postgresql.org/message-id/dbf77bf7-6e54-ed8a-c4ae-d196eeb664ce%40gmail.com
| From | Date | Subject | |
|---|---|---|---|
| Next Message | David Rowley | 2025-11-04 22:55:13 | Re: Teaching planner to short-circuit empty UNION/EXCEPT/INTERSECT inputs |
| Previous Message | John H | 2025-11-04 21:54:13 | Re: [PATCH] Add archive_mode=follow_primary to prevent unarchived WAL on standby promotion |