diff options
author | Walter Doekes <walter+asterisk@wjd.nu> | 2013-08-16 07:18:51 +0000 |
---|---|---|
committer | Walter Doekes <walter+asterisk@wjd.nu> | 2013-08-16 07:18:51 +0000 |
commit | c43e19e8e5fc5bc133f2ce3eeafbf9ce07048bd1 (patch) | |
tree | 3109874227e570a721bdd7f670a3f43a8ee39b4f /main/pbx.c | |
parent | 812355db8282eac83ddcd1969aea5bdd334e63a8 (diff) |
Prevent heap alloc functions from running out of stack space.
When asterisk has run out of memory (for whatever reason), the alloc
function logs a message. Logging requires memory. A recipe for
infinite recursion.
Stop the recursion by comparing the function call depth for sane values
before attempting another OOM log message.
Review: https://reviewboard.asterisk.org/r/2743/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@396822 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/pbx.c')
-rw-r--r-- | main/pbx.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/main/pbx.c b/main/pbx.c index 5000bf47b..730b526fe 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -7281,6 +7281,81 @@ static char *handle_show_switches(struct ast_cli_entry *e, int cmd, struct ast_c return CLI_SUCCESS; } +#if 0 +/* This code can be used to test if the system survives running out of memory. + * It might be an idea to put this in only if ENABLE_AUTODESTRUCT_TESTS is enabled. + * + * If you want to test this, these Linux sysctl flags might be appropriate: + * vm.overcommit_memory = 2 + * vm.swappiness = 0 + * + * <@Corydon76-home> I envision 'core eat disk space' and 'core eat file descriptors' now + * <@mjordan> egads + * <@mjordan> it's literally the 'big red' auto-destruct button + * <@mjordan> if you were wondering who even builds such a thing.... well, now you know + * ... + * <@Corydon76-home> What about if they lived only if you defined TEST_FRAMEWORK? Shouldn't have those on production machines + * <@mjordan> I think accompanied with an update to one of our README files that "no, really, TEST_FRAMEWORK isn't for you", I'd be fine + */ +static char *handle_eat_memory(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) +{ + void **blocks; + int blocks_pos = 0; + const int blocks_max = 50000; + long long int allocated = 0; + int sizes[] = { + 100 * 1024 * 1024, + 100 * 1024, + 2 * 1024, + 400, + 0 + }; + int i; + + switch (cmd) { + case CLI_INIT: + /* To do: add method to free memory again? 5 minutes? */ + e->command = "core eat memory"; + e->usage = + "Usage: core eat memory\n" + " Eats all available memory so you can test if the system survives\n"; + return NULL; + case CLI_GENERATE: + return NULL; + } + + blocks = ast_malloc(sizeof(void*) * blocks_max); + if (!blocks) { + ast_log(LOG_ERROR, "Already out of mem?\n"); + return CLI_SUCCESS; + } + + for (i = 0; sizes[i]; ++i) { + int alloc_size = sizes[i]; + ast_log(LOG_WARNING, "Allocating %d sized blocks (got %d blocks already)\n", alloc_size, blocks_pos); + while (1) { + void *block; + if (blocks_pos >= blocks_max) { + ast_log(LOG_ERROR, "Memory buffer too small? Run me again :)\n"); + break; + } + + block = ast_malloc(alloc_size); + if (!block) { + break; + } + + blocks[blocks_pos++] = block; + allocated += alloc_size; + } + } + + /* No freeing of the mem! */ + ast_log(LOG_WARNING, "Allocated %lld bytes total!\n", allocated); + return CLI_SUCCESS; +} +#endif + static char *handle_show_applications(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { struct ast_app *aa; @@ -8162,6 +8237,9 @@ static char *handle_unset_extenpatternmatchnew(struct ast_cli_entry *e, int cmd, * CLI entries for upper commands ... */ static struct ast_cli_entry pbx_cli[] = { +#if 0 + AST_CLI_DEFINE(handle_eat_memory, "Eats all available memory"), +#endif AST_CLI_DEFINE(handle_show_applications, "Shows registered dialplan applications"), AST_CLI_DEFINE(handle_show_functions, "Shows registered dialplan functions"), AST_CLI_DEFINE(handle_show_switches, "Show alternative switches"), |