bustd 0.1.1

Lightweight process killer daemon for out-of-memory scenarios
// `bustd`'s memory eater

#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

struct free_mem_s {
    unsigned available_mem_mib;
    unsigned available_swap_mib;
};

typedef struct free_mem_s free_mem_t;

void display(free_mem_t * mem, float psi) {
    printf("\rFree RAM: %d MiB. Free swap: %d MiB. PSI: %0.2f", mem->available_mem_mib, mem->available_swap_mib, psi);
    fflush(stdout);
}

float memory_pressure_some_avg_10(void) {
    FILE * memory_pressure = fopen("/proc/pressure/memory", "r");
    if(!memory_pressure) {
        perror("/proc/pressure/memory. Exiting.\n");
        fclose(memory_pressure);
        _exit(1);
    }

    float psi;

    if (EOF == fscanf(memory_pressure, "some avg10=%f", &psi)) {
        perror("Failed to read memory pressure values. Exiting.\n");
        fclose(memory_pressure);
        _exit(1);
    }

    fclose(memory_pressure);
    return psi;
}

free_mem_t poll_free_mem(void) {
    FILE * meminfo = fopen("/proc/meminfo", "r");
    if(!meminfo) {
        fprintf(stderr, "/proc/meminfo not found. Exiting.\n");
        fclose(meminfo);
        _exit(1);
    }

    char line[256];
    bool avail_mem_read = false;
    bool avail_swap_read = false;
    free_mem_t free_mem;

    while((!avail_mem_read || !avail_swap_read) && fgets(line, sizeof(line), meminfo))
    {
        int val;
        if(sscanf(line, "MemAvailable: %d kB", &val) == 1)
        {
            avail_mem_read = true;
            free_mem.available_mem_mib = (unsigned) val / 1024;
        }

        if(sscanf(line, "SwapFree: %d kB", &val) == 1)
        {
            avail_swap_read = true;
            free_mem.available_swap_mib = (unsigned) val / 1024;
        }
    }

    for (int i = 0; i < 100; i++) {
        putchar(' ');
    }

    if (!avail_swap_read || !avail_mem_read) {
        fprintf(stderr, "failed to read available system memory or swap amounts. Exiting.\n");
        fclose(meminfo);
        _exit(1);
    }

    fclose(meminfo);
    return free_mem;
}

int main(void) {
    time_t start, now;
    float time_left = 4.0;

    time(&start);

    while(time_left > 0.0) {
    	time(&now);
        time_left = 4.0 - difftime(now, start);

    	printf("\rmem-eater will start consuming system memory in: %.2f secs. Press Ctrl+C if you don't want that to happen.", time_left);
    	fflush(stdout);
    	usleep(20);
    }

    while(1)
    {
        free_mem_t free_mem = poll_free_mem();
        float psi = memory_pressure_some_avg_10();
        display(&free_mem, psi);
        void *m = malloc(1024*1024);
        memset(m,0,1024*1024);
    }


	return 0;
}