mirror of
https://github.com/jemalloc/jemalloc.git
synced 2026-07-22 04:03:11 +00:00
Compare commits
3 Commits
a6048680a8
...
4e903a0a32
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e903a0a32 | ||
|
|
07618496fc | ||
|
|
160ab9d7f6 |
15
.github/workflows/linux-ci.yml
vendored
15
.github/workflows/linux-ci.yml
vendored
@@ -508,6 +508,16 @@ jobs:
|
||||
CXX: g++
|
||||
CONFIGURE_FLAGS: "--enable-debug --enable-experimental-smallocx --enable-stats --enable-prof"
|
||||
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
||||
- env:
|
||||
CC: gcc
|
||||
CXX: g++
|
||||
CONFIGURE_FLAGS: --enable-cxx-infallible-new
|
||||
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
||||
- env:
|
||||
CC: gcc
|
||||
CXX: g++
|
||||
CONFIGURE_FLAGS: "--enable-cxx-infallible-new --enable-debug"
|
||||
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
@@ -637,6 +647,11 @@ jobs:
|
||||
CXX: g++
|
||||
CONFIGURE_FLAGS: "--with-malloc-conf=background_thread:true"
|
||||
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
||||
- env:
|
||||
CC: gcc
|
||||
CXX: g++
|
||||
CONFIGURE_FLAGS: --enable-cxx-infallible-new
|
||||
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
10
.github/workflows/macos-ci.yml
vendored
10
.github/workflows/macos-ci.yml
vendored
@@ -60,6 +60,11 @@ jobs:
|
||||
CXX: g++
|
||||
CONFIGURE_FLAGS: "--with-malloc-conf=percpu_arena:percpu"
|
||||
EXTRA_CFLAGS: "-Werror -Wno-array-bounds -Wno-unknown-warning-option -Wno-ignored-attributes -Wno-deprecated-declarations"
|
||||
- env:
|
||||
CC: gcc
|
||||
CXX: g++
|
||||
CONFIGURE_FLAGS: --enable-cxx-infallible-new
|
||||
EXTRA_CFLAGS: "-Werror -Wno-array-bounds -Wno-unknown-warning-option -Wno-ignored-attributes -Wno-deprecated-declarations"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
@@ -162,6 +167,11 @@ jobs:
|
||||
CXX: g++
|
||||
CONFIGURE_FLAGS: "--with-malloc-conf=percpu_arena:percpu"
|
||||
EXTRA_CFLAGS: "-Werror -Wno-array-bounds -Wno-unknown-warning-option -Wno-ignored-attributes -Wno-deprecated-declarations"
|
||||
- env:
|
||||
CC: gcc
|
||||
CXX: g++
|
||||
CONFIGURE_FLAGS: --enable-cxx-infallible-new
|
||||
EXTRA_CFLAGS: "-Werror -Wno-array-bounds -Wno-unknown-warning-option -Wno-ignored-attributes -Wno-deprecated-declarations"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
5
.github/workflows/windows-ci.yml
vendored
5
.github/workflows/windows-ci.yml
vendored
@@ -52,6 +52,11 @@ jobs:
|
||||
CXX: cl.exe
|
||||
CROSS_COMPILE_32BIT: yes
|
||||
CONFIGURE_FLAGS: --enable-debug
|
||||
- env:
|
||||
CC: gcc
|
||||
CXX: g++
|
||||
CONFIGURE_FLAGS: --enable-cxx-infallible-new
|
||||
EXTRA_CFLAGS: -fcommon
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
@@ -217,6 +217,15 @@ any of the following arguments (not a definitive list) to 'configure':
|
||||
Disable C++ integration. This will cause new and delete operator
|
||||
implementations to be omitted.
|
||||
|
||||
* `--enable-cxx-infallible-new`
|
||||
|
||||
Make the throwing `operator new` abort on allocation failure (logging the
|
||||
requested size) instead of throwing `std::bad_alloc`; the `std::nothrow`
|
||||
overloads still return null. Disabled by default, and has no effect when
|
||||
C++ integration is disabled (`--disable-cxx`). When enabled, under LTO
|
||||
this lets the compiler treat `operator new` as non-throwing and elide
|
||||
exception-handling cleanup in callers.
|
||||
|
||||
* `--with-xslroot=<path>`
|
||||
|
||||
Specify where to find DocBook XSL stylesheets when building the
|
||||
|
||||
@@ -349,8 +349,11 @@ ifeq (@enable_cxx@, 1)
|
||||
CPP_SRCS := $(srcroot)src/jemalloc_cpp.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
|
||||
ifeq (@enable_cxx_infallible_new@, 1)
|
||||
TESTS_INTEGRATION_CPP += $(srcroot)test/integration/cpp/infallible_new.cpp
|
||||
else
|
||||
TESTS_INTEGRATION_CPP += $(srcroot)test/integration/cpp/failing_new.cpp
|
||||
endif
|
||||
endif
|
||||
else
|
||||
CPP_SRCS :=
|
||||
|
||||
23
configure.ac
23
configure.ac
@@ -396,8 +396,31 @@ if test "x$enable_cxx" = "x1"; then
|
||||
enable_cxx_exceptions="0"
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl Do not enable infallible-new by default. When enabled, the throwing
|
||||
dnl operator new aborts on OOM (with size logged) instead of throwing
|
||||
dnl std::bad_alloc; nothrow new still returns null. With LTO this lets the
|
||||
dnl compiler prove operator new doesn't throw and elide exception cleanup.
|
||||
AC_ARG_ENABLE([cxx-infallible-new],
|
||||
[AS_HELP_STRING([--enable-cxx-infallible-new],
|
||||
[Abort on OOM in throwing operator new instead of throwing std::bad_alloc])],
|
||||
[if test "x$enable_cxx_infallible_new" = "xno" ; then
|
||||
enable_cxx_infallible_new="0"
|
||||
else
|
||||
enable_cxx_infallible_new="1"
|
||||
fi
|
||||
],
|
||||
[enable_cxx_infallible_new="0"]
|
||||
)
|
||||
if test "x$enable_cxx" != "x1" ; then
|
||||
enable_cxx_infallible_new="0"
|
||||
fi
|
||||
if test "x$enable_cxx_infallible_new" = "x1" ; then
|
||||
AC_DEFINE([JEMALLOC_INFALLIBLE_NEW], [ ], [ ])
|
||||
fi
|
||||
AC_SUBST([enable_cxx])
|
||||
AC_SUBST([enable_cxx_exceptions])
|
||||
AC_SUBST([enable_cxx_infallible_new])
|
||||
AC_SUBST([CONFIGURE_CXXFLAGS])
|
||||
AC_SUBST([SPECIFIED_CXXFLAGS])
|
||||
AC_SUBST([EXTRA_CXXFLAGS])
|
||||
|
||||
@@ -846,6 +846,16 @@ mallctl("arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".decay",
|
||||
build configuration.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry id="config.infallible_new">
|
||||
<term>
|
||||
<mallctl>config.infallible_new</mallctl>
|
||||
(<type>bool</type>)
|
||||
<literal>r-</literal>
|
||||
</term>
|
||||
<listitem><para><option>--enable-cxx-infallible-new</option> was
|
||||
specified during build configuration.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry id="config.lazy_lock">
|
||||
<term>
|
||||
<mallctl>config.lazy_lock</mallctl>
|
||||
|
||||
@@ -468,6 +468,13 @@
|
||||
/* Are C++ exceptions enabled? */
|
||||
#undef JEMALLOC_HAVE_CXX_EXCEPTIONS
|
||||
|
||||
/*
|
||||
* If defined, throwing operator new aborts on OOM (with size logged) instead
|
||||
* of throwing std::bad_alloc. Nothrow new still returns null. With LTO this
|
||||
* lets the compiler prove operator new is no-throw and elide exception cleanup.
|
||||
*/
|
||||
#undef JEMALLOC_INFALLIBLE_NEW
|
||||
|
||||
/* Performs additional size checks when defined. */
|
||||
#undef JEMALLOC_OPT_SIZE_CHECKS
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@ extern void (*JET_MUTABLE junk_alloc_callback)(void *ptr, size_t size);
|
||||
extern void (*JET_MUTABLE invalid_conf_abort)(void);
|
||||
extern bool opt_utrace;
|
||||
extern bool opt_xmalloc;
|
||||
extern bool opt_experimental_infallible_new;
|
||||
extern bool opt_experimental_tcache_gc;
|
||||
extern bool opt_zero;
|
||||
extern unsigned opt_narenas;
|
||||
|
||||
@@ -238,6 +238,18 @@ static const bool config_enable_cxx =
|
||||
#endif
|
||||
;
|
||||
|
||||
/*
|
||||
* Whether the throwing operator new aborts on OOM instead of throwing
|
||||
* std::bad_alloc (--enable-cxx-infallible-new).
|
||||
*/
|
||||
static const bool config_infallible_new =
|
||||
#ifdef JEMALLOC_INFALLIBLE_NEW
|
||||
true
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
;
|
||||
|
||||
#if defined(_WIN32) || defined(__APPLE__) || defined(JEMALLOC_HAVE_SCHED_GETCPU)
|
||||
/* Currently percpu_arena depends on sched_getcpu. */
|
||||
#define JEMALLOC_PERCPU_ARENA
|
||||
|
||||
@@ -276,6 +276,24 @@ def generate_linux_job(arch):
|
||||
}
|
||||
]
|
||||
|
||||
# --enable-cxx-infallible-new coverage. Plain variant runs on all arches;
|
||||
# debug-combined variant runs only on AMD64 to bound matrix size.
|
||||
infallible_new_entries = [
|
||||
{
|
||||
'CC': 'gcc',
|
||||
'CXX': 'g++',
|
||||
'CONFIGURE_FLAGS': '--enable-cxx-infallible-new',
|
||||
'EXTRA_CFLAGS': '-Werror -Wno-array-bounds'
|
||||
},
|
||||
]
|
||||
if arch == AMD64:
|
||||
infallible_new_entries.append({
|
||||
'CC': 'gcc',
|
||||
'CXX': 'g++',
|
||||
'CONFIGURE_FLAGS': '--enable-cxx-infallible-new --enable-debug',
|
||||
'EXTRA_CFLAGS': '-Werror -Wno-array-bounds'
|
||||
})
|
||||
|
||||
if arch == AMD64:
|
||||
for entry in manual_entries:
|
||||
job += " - env:\n"
|
||||
@@ -285,6 +303,14 @@ def generate_linux_job(arch):
|
||||
else:
|
||||
job += f" {key}: {value}\n"
|
||||
|
||||
for entry in infallible_new_entries:
|
||||
job += " - env:\n"
|
||||
for key, value in entry.items():
|
||||
if ' ' in str(value):
|
||||
job += f' {key}: "{value}"\n'
|
||||
else:
|
||||
job += f" {key}: {value}\n"
|
||||
|
||||
job += f"""
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
@@ -385,6 +411,24 @@ def generate_macos_job(arch):
|
||||
else:
|
||||
job += f" {key}: {value}\n"
|
||||
|
||||
# --enable-cxx-infallible-new coverage on macOS (both arches).
|
||||
macos_extra_cflags = ' '.join(get_extra_cflags(OSX, GCC.value))
|
||||
infallible_new_entries = [
|
||||
{
|
||||
'CC': 'gcc',
|
||||
'CXX': 'g++',
|
||||
'CONFIGURE_FLAGS': '--enable-cxx-infallible-new',
|
||||
'EXTRA_CFLAGS': macos_extra_cflags
|
||||
},
|
||||
]
|
||||
for entry in infallible_new_entries:
|
||||
job += " - env:\n"
|
||||
for key, value in entry.items():
|
||||
if ' ' in str(value) or any(c in str(value) for c in [':', ',', '#']):
|
||||
job += f' {key}: "{value}"\n'
|
||||
else:
|
||||
job += f" {key}: {value}\n"
|
||||
|
||||
job += f"""
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
@@ -467,6 +511,24 @@ def generate_windows_job(arch):
|
||||
else:
|
||||
job += f" {key}: {value}\n"
|
||||
|
||||
# --enable-cxx-infallible-new coverage on Windows (MinGW-GCC only).
|
||||
windows_mingw_cflags = ' '.join(get_extra_cflags(WINDOWS, GCC.value))
|
||||
infallible_new_entries = [
|
||||
{
|
||||
'CC': 'gcc',
|
||||
'CXX': 'g++',
|
||||
'CONFIGURE_FLAGS': '--enable-cxx-infallible-new',
|
||||
'EXTRA_CFLAGS': windows_mingw_cflags
|
||||
},
|
||||
]
|
||||
for entry in infallible_new_entries:
|
||||
job += " - env:\n"
|
||||
for key, value in entry.items():
|
||||
if ' ' in str(value) or any(c in str(value) for c in [':', ',', '#']):
|
||||
job += f' {key}: "{value}"\n'
|
||||
else:
|
||||
job += f" {key}: {value}\n"
|
||||
|
||||
job += f"""
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
@@ -731,11 +731,6 @@ malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS],
|
||||
if (config_xmalloc) {
|
||||
CONF_HANDLE_BOOL(opt_xmalloc, "xmalloc")
|
||||
}
|
||||
if (config_enable_cxx) {
|
||||
CONF_HANDLE_BOOL(
|
||||
opt_experimental_infallible_new,
|
||||
"experimental_infallible_new")
|
||||
}
|
||||
|
||||
CONF_HANDLE_BOOL(opt_experimental_tcache_gc,
|
||||
"experimental_tcache_gc")
|
||||
|
||||
@@ -182,7 +182,6 @@ void (*JET_MUTABLE invalid_conf_abort)(void) = &abort;
|
||||
|
||||
bool opt_utrace = false;
|
||||
bool opt_xmalloc = false;
|
||||
bool opt_experimental_infallible_new = false;
|
||||
bool opt_experimental_tcache_gc = true;
|
||||
bool opt_zero = false;
|
||||
unsigned opt_narenas = 0;
|
||||
|
||||
@@ -66,20 +66,20 @@ void operator delete[](
|
||||
JEMALLOC_NOINLINE
|
||||
static void *
|
||||
handleOOM(std::size_t size, bool nothrow) {
|
||||
if (opt_experimental_infallible_new) {
|
||||
const char *huge_warning = (size >= ((std::size_t)1 << 30))
|
||||
? "This may be caused by heap corruption, if the large size "
|
||||
"is unexpected (suggest building with sanitizers for "
|
||||
"debugging)."
|
||||
: "";
|
||||
|
||||
safety_check_fail(
|
||||
"<jemalloc>: Allocation of size %zu failed. "
|
||||
"%s opt.experimental_infallible_new is true. Aborting.\n",
|
||||
size, huge_warning);
|
||||
#ifdef JEMALLOC_INFALLIBLE_NEW
|
||||
if (nothrow) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char *huge_warning = (size >= ((std::size_t)1 << 30))
|
||||
? "This may be caused by heap corruption, if the large size "
|
||||
"is unexpected (suggest building with sanitizers for "
|
||||
"debugging). "
|
||||
: "";
|
||||
safety_check_fail(
|
||||
"<jemalloc>: Allocation of size %zu failed. %sAborting.\n",
|
||||
size, huge_warning);
|
||||
return nullptr;
|
||||
#else
|
||||
void *ptr = nullptr;
|
||||
|
||||
while (ptr == nullptr) {
|
||||
@@ -108,6 +108,7 @@ handleOOM(std::size_t size, bool nothrow) {
|
||||
#endif
|
||||
}
|
||||
return ptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <bool IsNoExcept>
|
||||
|
||||
@@ -1623,6 +1623,7 @@ stats_general_print(emitter_t *emitter) {
|
||||
CONFIG_WRITE_BOOL(cache_oblivious);
|
||||
CONFIG_WRITE_BOOL(debug);
|
||||
CONFIG_WRITE_BOOL(fill);
|
||||
CONFIG_WRITE_BOOL(infallible_new);
|
||||
CONFIG_WRITE_BOOL(lazy_lock);
|
||||
emitter_kv(emitter, "malloc_conf", "config.malloc_conf",
|
||||
emitter_type_string, &config_malloc_conf);
|
||||
@@ -1774,7 +1775,6 @@ stats_general_print(emitter_t *emitter) {
|
||||
OPT_WRITE_BOOL("zero")
|
||||
OPT_WRITE_BOOL("utrace")
|
||||
OPT_WRITE_BOOL("xmalloc")
|
||||
OPT_WRITE_BOOL("experimental_infallible_new")
|
||||
OPT_WRITE_BOOL("experimental_tcache_gc")
|
||||
OPT_WRITE_BOOL("tcache")
|
||||
OPT_WRITE_SIZE_T("tcache_max")
|
||||
|
||||
8
test/integration/cpp/failing_new.sh
Normal file
8
test/integration/cpp/failing_new.sh
Normal file
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
XMALLOC_STR=""
|
||||
if [ "x${enable_xmalloc}" = "x1" ] ; then
|
||||
XMALLOC_STR="xmalloc:false"
|
||||
fi
|
||||
|
||||
export MALLOC_CONF="${XMALLOC_STR}"
|
||||
@@ -3,8 +3,9 @@
|
||||
#include "test/jemalloc_test.h"
|
||||
|
||||
/*
|
||||
* We can't test C++ in unit tests. In order to intercept abort, use the
|
||||
* internal test hook in integration tests.
|
||||
* Verifies that, when jemalloc is built with --enable-cxx-infallible-new,
|
||||
* throwing operator new on OOM aborts via safety_check_fail. The test hook
|
||||
* intercepts the abort and asserts the size-bearing message prefix.
|
||||
*/
|
||||
bool fake_abort_called;
|
||||
void
|
||||
8
test/integration/cpp/infallible_new.sh
Normal file
8
test/integration/cpp/infallible_new.sh
Normal file
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
XMALLOC_STR=""
|
||||
if [ "x${enable_xmalloc}" = "x1" ] ; then
|
||||
XMALLOC_STR="xmalloc:false"
|
||||
fi
|
||||
|
||||
export MALLOC_CONF="${XMALLOC_STR}"
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
XMALLOC_STR=""
|
||||
if [ "x${enable_xmalloc}" = "x1" ] ; then
|
||||
XMALLOC_STR="xmalloc:false,"
|
||||
fi
|
||||
|
||||
export MALLOC_CONF="${XMALLOC_STR}experimental_infallible_new:false"
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
XMALLOC_STR=""
|
||||
if [ "x${enable_xmalloc}" = "x1" ] ; then
|
||||
XMALLOC_STR="xmalloc:false,"
|
||||
fi
|
||||
|
||||
export MALLOC_CONF="${XMALLOC_STR}experimental_infallible_new:true"
|
||||
File diff suppressed because it is too large
Load Diff
@@ -108,6 +108,32 @@ TEST_BEGIN(test_prof_backtrace_hook_replace) {
|
||||
|
||||
prof_backtrace_hook_t current_hook;
|
||||
size_t current_hook_sz = sizeof(prof_backtrace_hook_t);
|
||||
prof_backtrace_hook_t attempted_hook = &mock_bt_augmenting_hook;
|
||||
|
||||
current_hook_sz = sizeof(prof_backtrace_hook_t) - 1;
|
||||
expect_d_eq(mallctl("experimental.hooks.prof_backtrace",
|
||||
(void *)¤t_hook, ¤t_hook_sz,
|
||||
(void *)&attempted_hook, sizeof(attempted_hook)),
|
||||
EINVAL, "Unexpected mallctl success with malformed oldlen");
|
||||
|
||||
current_hook_sz = sizeof(prof_backtrace_hook_t);
|
||||
expect_d_eq(mallctl("experimental.hooks.prof_backtrace",
|
||||
(void *)¤t_hook, ¤t_hook_sz, NULL, 0),
|
||||
0, "Unexpected mallctl failure reading hook");
|
||||
expect_ptr_eq(current_hook, hook,
|
||||
"Malformed oldlen should not update hook");
|
||||
|
||||
expect_d_eq(mallctl("experimental.hooks.prof_backtrace", NULL, NULL,
|
||||
(void *)&attempted_hook, sizeof(attempted_hook) - 1),
|
||||
EINVAL, "Unexpected mallctl success with malformed newlen");
|
||||
|
||||
current_hook_sz = sizeof(prof_backtrace_hook_t);
|
||||
expect_d_eq(mallctl("experimental.hooks.prof_backtrace",
|
||||
(void *)¤t_hook, ¤t_hook_sz, NULL, 0),
|
||||
0, "Unexpected mallctl failure reading hook");
|
||||
expect_ptr_eq(current_hook, hook,
|
||||
"Malformed newlen should not update hook");
|
||||
|
||||
expect_d_eq(mallctl("experimental.hooks.prof_backtrace",
|
||||
(void *)¤t_hook, ¤t_hook_sz,
|
||||
(void *)&default_bt_hook, sizeof(default_bt_hook)),
|
||||
@@ -185,6 +211,32 @@ TEST_BEGIN(test_prof_dump_hook) {
|
||||
|
||||
prof_dump_hook_t current_hook;
|
||||
size_t current_hook_sz = sizeof(prof_dump_hook_t);
|
||||
prof_dump_hook_t attempted_hook = NULL;
|
||||
|
||||
current_hook_sz = sizeof(prof_dump_hook_t) - 1;
|
||||
expect_d_eq(mallctl("experimental.hooks.prof_dump",
|
||||
(void *)¤t_hook, ¤t_hook_sz,
|
||||
(void *)&attempted_hook, sizeof(attempted_hook)),
|
||||
EINVAL, "Unexpected mallctl success with malformed oldlen");
|
||||
|
||||
current_hook_sz = sizeof(prof_dump_hook_t);
|
||||
expect_d_eq(mallctl("experimental.hooks.prof_dump",
|
||||
(void *)¤t_hook, ¤t_hook_sz, NULL, 0),
|
||||
0, "Unexpected mallctl failure reading hook");
|
||||
expect_ptr_eq(current_hook, hook,
|
||||
"Malformed oldlen should not update hook");
|
||||
|
||||
expect_d_eq(mallctl("experimental.hooks.prof_dump", NULL, NULL,
|
||||
(void *)&attempted_hook, sizeof(attempted_hook) - 1),
|
||||
EINVAL, "Unexpected mallctl success with malformed newlen");
|
||||
|
||||
current_hook_sz = sizeof(prof_dump_hook_t);
|
||||
expect_d_eq(mallctl("experimental.hooks.prof_dump",
|
||||
(void *)¤t_hook, ¤t_hook_sz, NULL, 0),
|
||||
0, "Unexpected mallctl failure reading hook");
|
||||
expect_ptr_eq(current_hook, hook,
|
||||
"Malformed newlen should not update hook");
|
||||
|
||||
expect_d_eq(mallctl("experimental.hooks.prof_dump",
|
||||
(void *)¤t_hook, ¤t_hook_sz,
|
||||
(void *)&default_bt_hook, sizeof(default_bt_hook)),
|
||||
@@ -304,6 +356,42 @@ TEST_BEGIN(test_prof_sample_hooks) {
|
||||
write_prof_sample_free_hook(mock_prof_sample_free_hook);
|
||||
check_prof_sample_hooks(true, true);
|
||||
|
||||
prof_sample_hook_t attempted_sample_hook = NULL;
|
||||
prof_sample_hook_t sample_hook;
|
||||
size_t sample_hook_sz = sizeof(prof_sample_hook_t) - 1;
|
||||
expect_d_eq(mallctl("experimental.hooks.prof_sample",
|
||||
(void *)&sample_hook, &sample_hook_sz,
|
||||
(void *)&attempted_sample_hook,
|
||||
sizeof(attempted_sample_hook)),
|
||||
EINVAL, "Unexpected mallctl success with malformed oldlen");
|
||||
expect_ptr_eq(read_prof_sample_hook(), mock_prof_sample_hook,
|
||||
"Malformed oldlen should not update prof_sample hook");
|
||||
|
||||
expect_d_eq(mallctl("experimental.hooks.prof_sample", NULL, NULL,
|
||||
(void *)&attempted_sample_hook,
|
||||
sizeof(attempted_sample_hook) - 1),
|
||||
EINVAL, "Unexpected mallctl success with malformed newlen");
|
||||
expect_ptr_eq(read_prof_sample_hook(), mock_prof_sample_hook,
|
||||
"Malformed newlen should not update prof_sample hook");
|
||||
|
||||
prof_sample_free_hook_t attempted_sample_free_hook = NULL;
|
||||
prof_sample_free_hook_t sample_free_hook;
|
||||
size_t sample_free_hook_sz = sizeof(prof_sample_free_hook_t) - 1;
|
||||
expect_d_eq(mallctl("experimental.hooks.prof_sample_free",
|
||||
(void *)&sample_free_hook, &sample_free_hook_sz,
|
||||
(void *)&attempted_sample_free_hook,
|
||||
sizeof(attempted_sample_free_hook)),
|
||||
EINVAL, "Unexpected mallctl success with malformed oldlen");
|
||||
expect_ptr_eq(read_prof_sample_free_hook(), mock_prof_sample_free_hook,
|
||||
"Malformed oldlen should not update prof_sample_free hook");
|
||||
|
||||
expect_d_eq(mallctl("experimental.hooks.prof_sample_free", NULL, NULL,
|
||||
(void *)&attempted_sample_free_hook,
|
||||
sizeof(attempted_sample_free_hook) - 1),
|
||||
EINVAL, "Unexpected mallctl success with malformed newlen");
|
||||
expect_ptr_eq(read_prof_sample_free_hook(), mock_prof_sample_free_hook,
|
||||
"Malformed newlen should not update prof_sample_free hook");
|
||||
|
||||
write_prof_sample_hook(NULL);
|
||||
check_prof_sample_hooks(false, true);
|
||||
|
||||
@@ -311,12 +399,10 @@ TEST_BEGIN(test_prof_sample_hooks) {
|
||||
check_prof_sample_hooks(false, false);
|
||||
|
||||
/* Test read+write together. */
|
||||
prof_sample_hook_t sample_hook;
|
||||
read_write_prof_sample_hook(&sample_hook, true, mock_prof_sample_hook);
|
||||
expect_ptr_null(sample_hook, "Unexpected non NULL default hook");
|
||||
check_prof_sample_hooks(true, false);
|
||||
|
||||
prof_sample_free_hook_t sample_free_hook;
|
||||
read_write_prof_sample_free_hook(
|
||||
&sample_free_hook, true, mock_prof_sample_free_hook);
|
||||
expect_ptr_null(sample_free_hook, "Unexpected non NULL default hook");
|
||||
|
||||
Reference in New Issue
Block a user