Browse Source

Avoid getaddrinfo_a under ThreadSanitizer (#2631)

glibc runs getaddrinfo_a() lookups in a thread it creates internally,
bypassing the pthread_create interceptor, so TSan never initializes that
thread and it crashes on its first allocation. Detect TSan (GCC's
__SANITIZE_THREAD__ / Clang's __has_feature(thread_sanitizer)) and use the
existing std::thread-based fallback instead, which keeps the lookup timeout
working. Non-TSan builds are unchanged.
Cosmin Polifronie 2 ngày trước cách đây
mục cha
commit
16f9d4a68d
1 tập tin đã thay đổi với 11 bổ sung và 1 xóa
  1. 11 1
      httplib.h

+ 11 - 1
httplib.h

@@ -18,6 +18,14 @@
 #endif
 #endif
 
+#if defined(__SANITIZE_THREAD__)
+#define CPPHTTPLIB_THREAD_SANITIZER
+#elif defined(__has_feature)
+#if __has_feature(thread_sanitizer)
+#define CPPHTTPLIB_THREAD_SANITIZER
+#endif
+#endif
+
 /*
  * Configuration
  */
@@ -7017,7 +7025,9 @@ inline int getaddrinfo_with_timeout(const char *node, const char *service,
   *res = result_addrinfo;
   return 0;
 #elif defined(_GNU_SOURCE) && defined(__GLIBC__) &&                            \
-    (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2))
+    (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)) &&             \
+    !defined(CPPHTTPLIB_THREAD_SANITIZER)
+  // Skipped under TSan: glibc's internal resolver thread is invisible to it.
   // #2431: gai_cancel() is non-blocking and may return EAI_NOTCANCELED while
   // the resolver worker still references the stack-local gaicb. The cancel
   // path therefore waits (gai_suspend with no timeout) for the worker to