/*
 * To compile:
 *   gcc mallocfail.c -c -fPIC
 *   ld -ldl mallocfail.o -o mallocfail.so  -shared
 *
 * To run:
 *   MALLOC_FAIL_AT=110 LD_PRELOAD=mallocfail.so ./testlibpq
 */
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <execinfo.h>
#include <unistd.h>

static int counter = 0;
static int fail_at = -1;

void dump_core(void)
{
	if (!fork())
		abort();
}

void *(*orig_malloc)(size_t size);
 
void *malloc(size_t size)
{
	counter++;
	if (counter % 10 == 0)
		printf("malloc called: %d!\n", counter);
	if (counter == fail_at)
    {
		printf("malloc failing: %d!\n", counter);
		create_dump();
		return NULL;
    }
	return orig_malloc(size);
}

void
_init(void)
{
	char *fail_at_str = getenv("MALLOC_FAIL_AT");
	if (!fail_at_str)
		printf("FAIL_AT not set!\n");
	else
	{
		fail_at = atoi(fail_at_str);
		printf("FAIL_AT: %d\n", fail_at);
	}
  
	printf("loading malloc imposter.\n");
	orig_malloc = dlsym(RTLD_NEXT, "malloc");
}
