Skip to content
Snippets Groups Projects
Commit 8d53fadc authored by Cyrill Gorcunov's avatar Cyrill Gorcunov Committed by Kirill Yukhin
Browse files

fiber: leak slab if unable to bring prots back


In case if we unable to revert guard page back to
read|write we should never use such slab again.

Initially I thought of just put panic here and
exit but it is too destructive. I think better
print an error and continue. If node admin ignore
this message then one moment at future there won't
be slab left for use and creating new fibers get
prohibited.

In future (hopefully near one) we plan to drop
guard pages to prevent VMA fracturing and use
stack marks instead.

Reviewed-by: default avatarAlexander Turenko <alexander.turenko@tarantool.org>
Signed-off-by: default avatarCyrill Gorcunov <gorcunov@gmail.com>
parent c6752297
No related branches found
No related tags found
No related merge requests found
...@@ -1073,15 +1073,22 @@ fiber_stack_destroy(struct fiber *fiber, struct slab_cache *slabc) ...@@ -1073,15 +1073,22 @@ fiber_stack_destroy(struct fiber *fiber, struct slab_cache *slabc)
* to setup the original protection back in * to setup the original protection back in
* background. * background.
* *
* For now lets keep such slab referenced and
* leaked: if mprotect failed we must not allow
* to reuse such slab with PROT_NONE'ed page
* inside.
*
* Note that in case if we're called from * Note that in case if we're called from
* fiber_stack_create() the @a mprotect_flags is * fiber_stack_create() the @a mprotect_flags is
* the same as the slab been created with, so * the same as the slab been created with, so
* calling mprotect for VMA with same flags * calling mprotect for VMA with same flags
* won't fail. * won't fail.
*/ */
diag_log(); say_syserror("fiber: Can't put guard page to slab. "
"Leak %zu bytes", (size_t)fiber->stack_size);
} else {
slab_put(slabc, fiber->stack_slab);
} }
slab_put(slabc, fiber->stack_slab);
} }
} }
......
...@@ -15,11 +15,13 @@ noop_f(va_list ap) ...@@ -15,11 +15,13 @@ noop_f(va_list ap)
static int static int
main_f(va_list ap) main_f(va_list ap)
{ {
struct slab_cache *slabc = &cord()->slabc;
size_t used_before, used_after;
struct errinj *inj; struct errinj *inj;
struct fiber *fiber; struct fiber *fiber;
header(); header();
plan(4); plan(6);
/* /*
* Set non-default stack size to prevent reusing of an * Set non-default stack size to prevent reusing of an
...@@ -47,8 +49,7 @@ main_f(va_list ap) ...@@ -47,8 +49,7 @@ main_f(va_list ap)
ok(diag_get() != NULL, "mprotect: diag is armed after error"); ok(diag_get() != NULL, "mprotect: diag is armed after error");
/* /*
* Check madvise. We can't test the fiber destroy * Check madvise error on fiber creation.
* path since it is cleaning error.
*/ */
diag_clear(diag_get()); diag_clear(diag_get());
inj = errinj(ERRINJ_FIBER_MADVISE, ERRINJ_BOOL); inj = errinj(ERRINJ_FIBER_MADVISE, ERRINJ_BOOL);
...@@ -59,6 +60,35 @@ main_f(va_list ap) ...@@ -59,6 +60,35 @@ main_f(va_list ap)
ok(fiber != NULL, "madvise: non critical error on madvise hint"); ok(fiber != NULL, "madvise: non critical error on madvise hint");
ok(diag_get() != NULL, "madvise: diag is armed after error"); ok(diag_get() != NULL, "madvise: diag is armed after error");
/*
* Check if we leak on fiber destruction.
* We will print an error and result get
* compared by testing engine.
*/
fiber_attr_delete(fiber_attr);
fiber_attr = fiber_attr_new();
fiber_attr->flags |= FIBER_CUSTOM_STACK;
fiber_attr->stack_size = 64 << 10;
diag_clear(diag_get());
used_before = slabc->allocated.stats.used;
fiber = fiber_new_ex("test_madvise", fiber_attr, noop_f);
ok(fiber != NULL, "fiber with custom stack");
fiber_set_joinable(fiber, true);
inj = errinj(ERRINJ_FIBER_MPROTECT, ERRINJ_INT);
inj->iparam = PROT_READ | PROT_WRITE;
fiber_start(fiber);
fiber_join(fiber);
inj->iparam = -1;
used_after = slabc->allocated.stats.used;
ok(used_after > used_before, "expected leak detected");
fiber_attr_delete(fiber_attr);
footer(); footer();
ev_break(loop(), EVBREAK_ALL); ev_break(loop(), EVBREAK_ALL);
......
SystemError fiber mprotect failed: Cannot allocate memory SystemError fiber mprotect failed: Cannot allocate memory
fiber: Can't put guard page to slab. Leak 57344 bytes: Cannot allocate memory
*** main_f *** *** main_f ***
1..4 1..6
ok 1 - mprotect: failed to setup fiber guard page ok 1 - mprotect: failed to setup fiber guard page
ok 2 - mprotect: diag is armed after error ok 2 - mprotect: diag is armed after error
ok 3 - madvise: non critical error on madvise hint ok 3 - madvise: non critical error on madvise hint
ok 4 - madvise: diag is armed after error ok 4 - madvise: diag is armed after error
ok 5 - fiber with custom stack
ok 6 - expected leak detected
*** main_f: done *** *** main_f: done ***
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment