https://github.com/jemalloc/jemalloc/pull/2900.patch

From 3ff7e38fac4c261e78974f82e823c7b2f205ebd1 Mon Sep 17 00:00:00 2001
From: lexprfuncall <5360361+lexprfuncall@users.noreply.github.com>
Date: Thu, 23 Apr 2026 11:56:38 -0700
Subject: [PATCH 1/2] Replace std::__throw_bad_alloc call with standard C++

Since December of 2025, std::__throw_bad_alloc is no longer visible
through #include <new> causing jemalloc build failures with gcc 16.
As far as I can tell, all std::__throw_bad_alloc did was arrange to
raise a std::bad_alloc exception if exceptions are enabled.  I am not
sure whether its usage was truly meaningful in jemalloc since the call
is wrapped in a try catch and any usage of try catch is considered an
error when compiling with -fno-exceptions on gcc, at least.

This change adds a check to configure.ac that determines whether
exceptions are enabled by compiling a simple try catch that raises a
std::bad_alloc exception.  If that test succeeds, the macro
JEMALLOC_HAVE_CXX_EXCEPTIONS is defined, and jemalloc will raise an
exception.  Otherwise, we call std::terminate() to abort.

This was tested on FreeBSD with the gcc16 port with and without exceptions
enabled.
---
 Makefile.in                                   |  6 +++--
 configure.ac                                  | 23 +++++++++++++++++++
 .../internal/jemalloc_internal_defs.h.in      |  3 +++
 src/jemalloc_cpp.cpp                          | 14 +++++++++--
 4 files changed, 42 insertions(+), 4 deletions(-)

diff --git a/Makefile.in b/Makefile.in
index a93048d7b8..1f9d14f1f2 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -337,9 +337,11 @@ TESTS_INTEGRATION += \
 endif
 ifeq (@enable_cxx@, 1)
 CPP_SRCS := $(srcroot)src/jemalloc_cpp.cpp
-TESTS_INTEGRATION_CPP := $(srcroot)test/integration/cpp/basic.cpp \
-	$(srcroot)test/integration/cpp/infallible_new_true.cpp \
+TESTS_INTEGRATION_CPP := $(srcroot)test/integration/cpp/basic.cpp
+ifeq (@enable_cxx_exceptions@, 1)
+TESTS_INTEGRATION_CPP += $(srcroot)test/integration/cpp/infallible_new_true.cpp \
 	$(srcroot)test/integration/cpp/infallible_new_false.cpp
+endif
 else
 CPP_SRCS :=
 TESTS_INTEGRATION_CPP :=
diff --git a/configure.ac b/configure.ac
index 321a729012..d151829832 100644
--- a/configure.ac
+++ b/configure.ac
@@ -374,7 +374,30 @@ fi
 if test "x$enable_cxx" = "x1"; then
   AC_DEFINE([JEMALLOC_ENABLE_CXX], [ ], [ ])
 fi
+if test "x$enable_cxx" = "x1"; then
+  dnl Now check whether the C++ compiler has exceptions enabled.
+  AC_LANG_PUSH([C++])
+  SAVED_CXXFLAGS="${CXXFLAGS}"
+  CXXFLAGS="${CXXFLAGS} ${EXTRA_CXXFLAGS}"
+  JE_COMPILABLE([C++ exception support], [
+#include <new>
+], [
+	try {
+		throw std::bad_alloc();
+	} catch (const std::bad_alloc &) {
+	}
+], [je_cv_cxx_exceptions])
+  CXXFLAGS="${SAVED_CXXFLAGS}"
+  AC_LANG_POP([C++])
+  if test "x${je_cv_cxx_exceptions}" = "xyes" ; then
+    AC_DEFINE([JEMALLOC_HAVE_CXX_EXCEPTIONS], [ ], [ ])
+    enable_cxx_exceptions="1"
+  else
+    enable_cxx_exceptions="0"
+  fi
+fi
 AC_SUBST([enable_cxx])
+AC_SUBST([enable_cxx_exceptions])
 AC_SUBST([CONFIGURE_CXXFLAGS])
 AC_SUBST([SPECIFIED_CXXFLAGS])
 AC_SUBST([EXTRA_CXXFLAGS])
diff --git a/include/jemalloc/internal/jemalloc_internal_defs.h.in b/include/jemalloc/internal/jemalloc_internal_defs.h.in
index 31ae2e8ed2..54d4da2032 100644
--- a/include/jemalloc/internal/jemalloc_internal_defs.h.in
+++ b/include/jemalloc/internal/jemalloc_internal_defs.h.in
@@ -465,6 +465,9 @@
 /* Is C++ support being built? */
 #undef JEMALLOC_ENABLE_CXX
 
+/* Are C++ exceptions enabled? */
+#undef JEMALLOC_HAVE_CXX_EXCEPTIONS
+
 /* Performs additional size checks when defined. */
 #undef JEMALLOC_OPT_SIZE_CHECKS
 
diff --git a/src/jemalloc_cpp.cpp b/src/jemalloc_cpp.cpp
index 4e838d3b51..d1272879b0 100644
--- a/src/jemalloc_cpp.cpp
+++ b/src/jemalloc_cpp.cpp
@@ -1,3 +1,4 @@
+#include <exception>
 #include <mutex>
 #include <new>
 // NOLINTBEGIN(misc-use-anonymous-namespace)
@@ -90,17 +91,26 @@ handleOOM(std::size_t size, bool nothrow) {
 		if (handler == nullptr)
 			break;
 
+#ifdef JEMALLOC_HAVE_CXX_EXCEPTIONS
 		try {
 			handler();
 		} catch (const std::bad_alloc &) {
 			break;
 		}
+#else
+		handler();
+#endif
 
 		ptr = je_malloc(size);
 	}
 
-	if (ptr == nullptr && !nothrow)
-		std::__throw_bad_alloc();
+	if (ptr == nullptr && !nothrow) {
+#ifdef JEMALLOC_HAVE_CXX_EXCEPTIONS
+		throw std::bad_alloc();
+#else
+		std::terminate();
+#endif
+	}
 	return ptr;
 }
 

From b68e7627d6c5e00055e31ee6846bea33844fccfe Mon Sep 17 00:00:00 2001
From: lexprfuncall <5360361+lexprfuncall@users.noreply.github.com>
Date: Mon, 27 Apr 2026 11:00:22 -0700
Subject: [PATCH 2/2] Replace std::set_new_handler calls with
 std::get_new_handler

Previously, std::set_new_handler was used as a workaround for
compilers with only partial support for C++11.  Now that C++14 is a
requirement to enable C++ support, we can assume std::get_new_handler
is available.
---
 src/jemalloc_cpp.cpp | 11 +----------
 1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/src/jemalloc_cpp.cpp b/src/jemalloc_cpp.cpp
index d1272879b0..ac109bb28e 100644
--- a/src/jemalloc_cpp.cpp
+++ b/src/jemalloc_cpp.cpp
@@ -1,5 +1,4 @@
 #include <exception>
-#include <mutex>
 #include <new>
 // NOLINTBEGIN(misc-use-anonymous-namespace)
 
@@ -79,15 +78,7 @@ handleOOM(std::size_t size, bool nothrow) {
 	void *ptr = nullptr;
 
 	while (ptr == nullptr) {
-		std::new_handler handler;
-		// GCC-4.8 and clang 4.0 do not have std::get_new_handler.
-		{
-			static std::mutex           mtx;
-			std::lock_guard<std::mutex> lock(mtx);
-
-			handler = std::set_new_handler(nullptr);
-			std::set_new_handler(handler);
-		}
+		std::new_handler handler = std::get_new_handler();
 		if (handler == nullptr)
 			break;
 
