diff options
author | Kostya Kortchinsky <kostyak@google.com> | 2017-11-15 16:40:27 +0000 |
---|---|---|
committer | Kostya Kortchinsky <kostyak@google.com> | 2017-11-15 16:40:27 +0000 |
commit | 0066b15e48e7b40e43051c9241760e7066582a96 (patch) | |
tree | 5de4cf2a712c94e2f541d687100b1144353ccf89 /test | |
parent | e811c409bf2634f1845f5f14e36851255098b197 (diff) |
[scudo] Soft and hard RSS limit checks
Summary:
This implements an opportunistic check for the RSS limit.
For ASan, this was implemented thanks to a background thread checking the
current RSS vs the set limit every 100ms. This was deemed problematic for Scudo
due to potential Android concerns (Zygote as pointed out by Aleksey) as well as
the general inconvenience of having a permanent background thread.
If a limit (soft or hard) is specified, we will attempt to update the RSS limit
status (exceeded or not) every 100ms. This is done in an opportunistic way: if
we can update it, we do it, if not we return the current status, mostly because
we don't need it to be fully consistent (it's done every 100ms anyway). If the
limit is exceeded `allocate` will act as if OOM for a soft limit, or just die
for a hard limit.
We use the `common_flags()`'s `hard_rss_limit_mb` & `soft_rss_limit_mb` for
configuration of the limits.
Reviewers: alekseyshl
Reviewed By: alekseyshl
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D40038
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@318301 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test')
-rw-r--r-- | test/scudo/rss.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/test/scudo/rss.c b/test/scudo/rss.c new file mode 100644 index 000000000..4376290ad --- /dev/null +++ b/test/scudo/rss.c @@ -0,0 +1,56 @@ +// RUN: %clang_scudo %s -o %t +// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-nolimit +// RUN: %env_scudo_opts="soft_rss_limit_mb=256" %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-nolimit +// RUN: %env_scudo_opts="hard_rss_limit_mb=256" %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-nolimit +// RUN: %env_scudo_opts="soft_rss_limit_mb=64:allocator_may_return_null=0" not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-softlimit +// RUN: %env_scudo_opts="soft_rss_limit_mb=64:allocator_may_return_null=1" %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-softlimit-returnnull +// RUN: %env_scudo_opts="soft_rss_limit_mb=64:allocator_may_return_null=0:can_use_proc_maps_statm=0" not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-softlimit +// RUN: %env_scudo_opts="soft_rss_limit_mb=64:allocator_may_return_null=1:can_use_proc_maps_statm=0" %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-softlimit-returnnull +// RUN: %env_scudo_opts="hard_rss_limit_mb=64:allocator_may_return_null=0" not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-hardlimit +// RUN: %env_scudo_opts="hard_rss_limit_mb=64:allocator_may_return_null=1" not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-hardlimit +// RUN: %env_scudo_opts="hard_rss_limit_mb=64:allocator_may_return_null=0:can_use_proc_maps_statm=0" not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-hardlimit +// RUN: %env_scudo_opts="hard_rss_limit_mb=64:allocator_may_return_null=1:can_use_proc_maps_statm=0" not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-hardlimit + +// Tests that the soft and hard RSS limits work as intended. Without limit or +// with a high limit, the test should pass without any malloc returning NULL or +// the program dying. +// If a limit is specified, it should return some NULL or die depending on +// allocator_may_return_null. This should also work without statm. + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +static const size_t kNumAllocs = 128; +static const size_t kAllocSize = 1 << 20; // 1MB. + +static void *allocs[kNumAllocs]; + +int main(int argc, char *argv[]) { + int returned_null = 0; + for (int i = 0; i < kNumAllocs; i++) { + if ((i & 0xf) == 0) + usleep(50000); + allocs[i] = malloc(kAllocSize); + if (allocs[i]) + memset(allocs[i], 0xff, kAllocSize); // Dirty the pages. + else + returned_null++; + } + for (int i = 0; i < kNumAllocs; i++) + free(allocs[i]); + if (returned_null == 0) + printf("All malloc calls succeeded\n"); + else + printf("%d malloc calls returned NULL\n", returned_null); + return 0; +} + +// CHECK-nolimit: All malloc calls succeeded +// CHECK-softlimit: soft RSS limit exhausted +// CHECK-softlimit-NOT: malloc calls +// CHECK-softlimit-returnnull: soft RSS limit exhausted +// CHECK-softlimit-returnnull: malloc calls returned NULL +// CHECK-hardlimit: hard RSS limit exhausted +// CHECK-hardlimit-NOT: malloc calls |