23#include <sys/resource.h>
33#define RAMBLOCKS_MAX 1000
41static int checked_getrlimit(
int resource,
struct rlimit *rlim) {
43 if (getrlimit(resource, rlim) != 0) {
45 fprintf (stderr,
"%s:%d getrlimit() failed with errno=%d %s\n",
46 __FILE__,__LINE__, errno,strerror(errno));
60static size_t oomfill_fill_preinit(
const size_t minHeap,
const size_t minStack) {
63 assert(NULL==_oomblocks[0]);
96size_t (*
oomfill_fill)(
const size_t minHeap,
const size_t minStack)=oomfill_fill_preinit;
106static void oomfill_free_preinit() {
107 assert(NULL==_oomblocks[0]);
135static size_t oomfill_enable_preinit(
const size_t softlimit) {
139 fprintf(stderr,
"%s:%d oomfill_enable called without oomfill_config before\n",__FILE__,__LINE__);
181static size_t oomfill_disable_preinit() {
183 fprintf(stderr,
"%s:%d oomfill_disable called without oomfill_config before\n",__FILE__,__LINE__);
223static size_t oomfill_getbiggestblock(
void** p_ramblock) {
235 static size_t max,cur;
236 static struct rlimit limit;
238 assert(NULL!=p_ramblock);
239 assert(NULL==*p_ramblock);
242 checked_getrlimit(RLIMIT_AS, &limit);
243 max = limit.rlim_cur;
246 while ((max>0)&&(NULL==*p_ramblock)) {
251 cur = min+(max-min)/2;
252 if (NULL==(*p_ramblock =
malloc(cur))) {
273static size_t oomfill_fill_postinit(
const size_t minHeap,
const size_t minStack) {
274 unsigned int l_numblock;
276 void*
volatile l_reservedheap;
277 void* l_reservedstack;
280 if (NULL!=_oomblocks[0]) {
283 fprintf (stderr,
"%s:%d oomblocks are already allocated\n", __FILE__,__LINE__);
291 l_reservedstack=alloca(minStack);
292 (void)l_reservedstack;
297 if (NULL==(l_reservedheap=
malloc(minHeap))) {
299 fprintf(stderr,
"%s:%d Failed to reserve minheap bytes\n",__FILE__,__LINE__);
307 l_sum += oomfill_getbiggestblock(&(_oomblocks[l_numblock++]));
308 while ((NULL!=_oomblocks[l_numblock-1])&&((
RAMBLOCKS_MAX-1)>l_numblock))
309 l_sum += oomfill_getbiggestblock(&(_oomblocks[l_numblock++]));
313 _oomblocks[l_numblock]=NULL;
318 if (NULL!=l_reservedheap)
319 free(l_reservedheap);
331static void oomfill_free_postinit() {
335 if (NULL==_oomblocks[0]) {
336 fprintf(stderr,
"%s:%d no blocks to free in oomfill_free.\n",__FILE__,__LINE__);
343 free(_oomblocks[l_i]);
344 _oomblocks[l_i] = NULL;
356static size_t oomfill_enable_postinit(
const size_t softlimit) {
358 size_t l_softlimit = softlimit;
361 assert(NULL==_oomblocks[0]);
364 checked_getrlimit(RLIMIT_AS, &limit);
367 if (0==l_softlimit) {
369 l_softlimit = limit.rlim_max;
373 limit.rlim_cur = l_softlimit;
376 if (setrlimit(RLIMIT_AS, &limit) != 0) {
377 fprintf (stderr,
"%s:%d setrlimit(cur=%lu, max=%lu) with errno=%d %s\n",
379 (
unsigned long)limit.rlim_cur, (
unsigned long)limit.rlim_max,
380 errno,strerror(errno));
389 return limit.rlim_cur;
399static size_t oomfill_disable_postinit() {
402 if (NULL!=_oomblocks[0]) {
403 fprintf(stderr,
"%s:%d RAM still allocated while calling oomfill_disable\n",__FILE__,__LINE__);
409 fprintf(stderr,
"%s:%d Impossible to disable oomfill if not previously enabled\n",__FILE__,__LINE__);
414 oomfill_enable_postinit(0);
417 checked_getrlimit(RLIMIT_AS, &limit);
424 return limit.rlim_cur;
460 size_t l_hardlimit = hardlimit;
463 if (NULL!=_oomblocks[0]) {
464 fprintf(stderr,
"%s:%d Calling oomfill_config with allocated RAM blocks is not allowed.\n",
470 l_avail = (sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE));
473 checked_getrlimit(RLIMIT_AS, &limit);
474 if (0==l_hardlimit) {
477 l_hardlimit=(limit.rlim_max<l_avail?limit.rlim_max:l_avail);
478 }
else if (l_hardlimit>l_avail) {
480 fprintf(stderr,
"%s:%d Requesing a limit %lu bigger than *installed* RAM %lu is not allowed.\n",
482 (
unsigned long)l_hardlimit,(
unsigned long)l_avail);
487 limit.rlim_cur = l_hardlimit;
488 limit.rlim_max = l_hardlimit;
491 if (setrlimit(RLIMIT_AS, &limit) != 0) {
492 fprintf (stderr,
"%s:%d setrlimit(cur=%lu, max=%lu) with errno=%d %s\n",
493 __FILE__,__LINE__, (
unsigned long)limit.rlim_cur,
494 (
unsigned long)limit.rlim_max, errno,strerror(errno));
496 checked_getrlimit(RLIMIT_AS, &limit);
497 fprintf (stderr,
"%s:%d getrlimit() is cur=%lu, max=%lu\n",
498 __FILE__,__LINE__, (
unsigned long)limit.rlim_cur,
499 (
unsigned long)limit.rlim_max);
508 return limit.rlim_max;
512 return (
oomfill_fill==oomfill_fill_postinit?
true:
false);
size_t(* oomfill_disable)()
Stops the current oomfill.
#define RAMBLOCKS_MAX
Maximum number of fragmented blocks to allocate.
size_t(* oomfill_enable)(const size_t softlimit)
Starts a new oomfill environment or reconfigure the soft limit.
size_t(* oomfill_fill)(const size_t minHeap, const size_t minStack)
Starts an almost OOM single and simple test.
void(* oomfill_free)()
Ends a single simple OOM test.
size_t oomfill_config(const size_t hardlimit)
Sets the oomfill helpers hard rlimit and enables the oomfill helper features.
Library safely (rlimited) consumming RAM to trigger OOMs (only on POSIX systems)
void * malloc(size_t size)
stdc malloc stub function