Hooks: Add a hook exhaustion test.
When we run out of space in which to store hooks, we should return EAGAIN from the mallctl, but not otherwise misbehave.
This commit is contained in:
parent
bb071db92e
commit
59e371f463
@ -46,6 +46,8 @@
|
|||||||
* order.
|
* order.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define HOOK_MAX 4
|
||||||
|
|
||||||
enum hook_alloc_e {
|
enum hook_alloc_e {
|
||||||
hook_alloc_malloc,
|
hook_alloc_malloc,
|
||||||
hook_alloc_posix_memalign,
|
hook_alloc_posix_memalign,
|
||||||
|
@ -14,9 +14,8 @@ struct hooks_internal_s {
|
|||||||
|
|
||||||
seq_define(hooks_internal_t, hooks)
|
seq_define(hooks_internal_t, hooks)
|
||||||
|
|
||||||
#define HOOKS_MAX 4
|
|
||||||
static atomic_u_t nhooks = ATOMIC_INIT(0);
|
static atomic_u_t nhooks = ATOMIC_INIT(0);
|
||||||
static seq_hooks_t hooks[HOOKS_MAX];
|
static seq_hooks_t hooks[HOOK_MAX];
|
||||||
static malloc_mutex_t hooks_mu;
|
static malloc_mutex_t hooks_mu;
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -28,7 +27,7 @@ hook_boot() {
|
|||||||
static void *
|
static void *
|
||||||
hook_install_locked(hooks_t *to_install) {
|
hook_install_locked(hooks_t *to_install) {
|
||||||
hooks_internal_t hooks_internal;
|
hooks_internal_t hooks_internal;
|
||||||
for (int i = 0; i < HOOKS_MAX; i++) {
|
for (int i = 0; i < HOOK_MAX; i++) {
|
||||||
bool success = seq_try_load_hooks(&hooks_internal, &hooks[i]);
|
bool success = seq_try_load_hooks(&hooks_internal, &hooks[i]);
|
||||||
/* We hold mu; no concurrent access. */
|
/* We hold mu; no concurrent access. */
|
||||||
assert(success);
|
assert(success);
|
||||||
@ -74,7 +73,7 @@ void
|
|||||||
hook_remove(tsdn_t *tsdn, void *opaque) {
|
hook_remove(tsdn_t *tsdn, void *opaque) {
|
||||||
if (config_debug) {
|
if (config_debug) {
|
||||||
char *hooks_begin = (char *)&hooks[0];
|
char *hooks_begin = (char *)&hooks[0];
|
||||||
char *hooks_end = (char *)&hooks[HOOKS_MAX];
|
char *hooks_end = (char *)&hooks[HOOK_MAX];
|
||||||
char *hook = (char *)opaque;
|
char *hook = (char *)opaque;
|
||||||
assert(hooks_begin <= hook && hook < hooks_end
|
assert(hooks_begin <= hook && hook < hooks_end
|
||||||
&& (hook - hooks_begin) % sizeof(seq_hooks_t) == 0);
|
&& (hook - hooks_begin) % sizeof(seq_hooks_t) == 0);
|
||||||
@ -87,7 +86,7 @@ hook_remove(tsdn_t *tsdn, void *opaque) {
|
|||||||
|
|
||||||
#define FOR_EACH_HOOK_BEGIN(hooks_internal_ptr) \
|
#define FOR_EACH_HOOK_BEGIN(hooks_internal_ptr) \
|
||||||
for (int for_each_hook_counter = 0; \
|
for (int for_each_hook_counter = 0; \
|
||||||
for_each_hook_counter < HOOKS_MAX; \
|
for_each_hook_counter < HOOK_MAX; \
|
||||||
for_each_hook_counter++) { \
|
for_each_hook_counter++) { \
|
||||||
bool for_each_hook_success = seq_try_load_hooks( \
|
bool for_each_hook_success = seq_try_load_hooks( \
|
||||||
(hooks_internal_ptr), &hooks[for_each_hook_counter]); \
|
(hooks_internal_ptr), &hooks[for_each_hook_counter]); \
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "test/jemalloc_test.h"
|
#include "test/jemalloc_test.h"
|
||||||
|
|
||||||
|
#include "jemalloc/internal/hook.h"
|
||||||
#include "jemalloc/internal/util.h"
|
#include "jemalloc/internal/util.h"
|
||||||
|
|
||||||
TEST_BEGIN(test_mallctl_errors) {
|
TEST_BEGIN(test_mallctl_errors) {
|
||||||
@ -810,6 +811,42 @@ TEST_BEGIN(test_hooks) {
|
|||||||
}
|
}
|
||||||
TEST_END
|
TEST_END
|
||||||
|
|
||||||
|
TEST_BEGIN(test_hooks_exhaustion) {
|
||||||
|
bool hook_called = false;
|
||||||
|
hooks_t hooks = {&alloc_hook, &dalloc_hook, NULL, &hook_called};
|
||||||
|
|
||||||
|
void *handle;
|
||||||
|
void *handles[HOOK_MAX];
|
||||||
|
size_t sz = sizeof(handle);
|
||||||
|
int err;
|
||||||
|
for (int i = 0; i < HOOK_MAX; i++) {
|
||||||
|
handle = NULL;
|
||||||
|
err = mallctl("experimental.hooks.install", &handle, &sz,
|
||||||
|
&hooks, sizeof(hooks));
|
||||||
|
assert_d_eq(err, 0, "Error installation hooks");
|
||||||
|
assert_ptr_ne(handle, NULL, "Got NULL handle");
|
||||||
|
handles[i] = handle;
|
||||||
|
}
|
||||||
|
err = mallctl("experimental.hooks.install", &handle, &sz, &hooks,
|
||||||
|
sizeof(hooks));
|
||||||
|
assert_d_eq(err, EAGAIN, "Should have failed hook installation");
|
||||||
|
for (int i = 0; i < HOOK_MAX; i++) {
|
||||||
|
err = mallctl("experimental.hooks.remove", NULL, NULL,
|
||||||
|
&handles[i], sizeof(handles[i]));
|
||||||
|
assert_d_eq(err, 0, "Hook removal failed");
|
||||||
|
}
|
||||||
|
/* Insertion failed, but then we removed some; it should work now. */
|
||||||
|
handle = NULL;
|
||||||
|
err = mallctl("experimental.hooks.install", &handle, &sz, &hooks,
|
||||||
|
sizeof(hooks));
|
||||||
|
assert_d_eq(err, 0, "Hook insertion failed");
|
||||||
|
assert_ptr_ne(handle, NULL, "Got NULL handle");
|
||||||
|
err = mallctl("experimental.hooks.remove", NULL, NULL, &handle,
|
||||||
|
sizeof(handle));
|
||||||
|
assert_d_eq(err, 0, "Hook removal failed");
|
||||||
|
}
|
||||||
|
TEST_END
|
||||||
|
|
||||||
int
|
int
|
||||||
main(void) {
|
main(void) {
|
||||||
return test(
|
return test(
|
||||||
@ -839,5 +876,6 @@ main(void) {
|
|||||||
test_arenas_create,
|
test_arenas_create,
|
||||||
test_arenas_lookup,
|
test_arenas_lookup,
|
||||||
test_stats_arenas,
|
test_stats_arenas,
|
||||||
test_hooks);
|
test_hooks,
|
||||||
|
test_hooks_exhaustion);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user