diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..5fa3f4c --- /dev/null +++ b/.clang-format @@ -0,0 +1,12 @@ + +--- +Language: Cpp +BasedOnStyle: LLVM +DerivePointerAlignment: false +PointerAlignment: Left +SortIncludes: false + +# Regroup causes unnecessary noise due to clang-format bug. +IncludeBlocks: Preserve + +--- diff --git a/LICENSE b/LICENSE index 0cb3c48..de70cfc 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2021, Edoardo Sanguineti +Copyright (c) 2022, Edoardo Sanguineti All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/common.c b/common.c index 8097d50..104819b 100644 --- a/common.c +++ b/common.c @@ -1,15 +1,14 @@ +#include +#include + #include "common.h" // Prints the time -void printTimeStamp(FILE *fp) -{ - time_t ltime; - struct tm result; - char stime[32]; - bzero(stime, sizeof(stime)); +void get_time_stamp(char* buf) { + time_t ltime; + struct tm result; - ltime = time(NULL); - localtime_r(<ime, &result); - asctime_r(&result, stime); - fprintf(fp, "\nTimeStamp: %s\n", stime); + ltime = time(NULL); + localtime_r(<ime, &result); + asctime_r(&result, buf); } diff --git a/common.h b/common.h index 1209693..807d226 100644 --- a/common.h +++ b/common.h @@ -1,16 +1,8 @@ #ifndef COMMON_H #define COMMON_H -#include -#include -#include -#include -#include -#include -#include - -void printTimeStamp(FILE *fp); - #define BUFFER_SIZE 4096 +void get_time_stamp(char* buf); + #endif /* COMMON_H */ diff --git a/main.c b/main.c index dcc15b6..0b0bf60 100644 --- a/main.c +++ b/main.c @@ -1,35 +1,38 @@ -#include "common.h" +#include #include +#include + +#include "common.h" #include "monitor.h" volatile sig_atomic_t sigint_received = 0; -void sigint_handler(int a) -{ - sigint_received = 1; -} +void sigint_handler(int a) { sigint_received = 1; } -int main(int argc, char *argv[]) -{ - if (argc < 2) - { - printf("Name of the program is missing\n"); - printf("Usage: \n"); - return 2; +int main(int argc, char* argv[]) { + if (argc < 2) { + printf("Name of the program is missing\n"); + printf("Usage: \n"); + return 2; + } + + struct sigaction act; + act.sa_handler = sigint_handler; + sigaction(SIGINT, &act, NULL); + + int result = setup(argv[1]); + if (result) { + return 1; + } + + while (!sigint_received) { + if (analyse()) { + return 3; } - struct sigaction act; - act.sa_handler = sigint_handler; - sigaction(SIGINT, &act, NULL); + sleep(10); + } - setup(argv[1]); - - while (!sigint_received) - { - analyse(); - sleep(10); - } - - printf("Normal shutdown\n"); - return 0; + printf("Normal shutdown\n"); + return 0; } diff --git a/makefile b/makefile index f2cfd81..60be301 100644 --- a/makefile +++ b/makefile @@ -1,7 +1,7 @@ -TARGET = prog +TARGET = monitor LIBS = -lm CC = gcc -CFLAGS = -O2 -g -Wall +CFLAGS = -O2 -g -Wall -std=gnu11 .PHONY: clean all default diff --git a/monitor.c b/monitor.c index 99db9fc..df06301 100644 --- a/monitor.c +++ b/monitor.c @@ -1,165 +1,170 @@ -#include "common.h" +#include +#include +#include +#include #include -#include "monitor.h" -#include "utils.h" #include -#include + +#include "common.h" +#include "utils.h" +#include "monitor.h" #define MAX_MEMORY 1048576 #define MAX_TRACK_SIZE 30 -FILE *popen(const char *command, const char *mode); -int pclose(FILE *stream); -char *strerror(int errnum); +FILE* popen(const char* command, const char* type); +int pclose(FILE* stream); +char* strerror(int errnum); -void printGenericStatusError() -{ - printf("Error while parsing file\n"); - printf("Processes may be monitored incorrectly\n"); +static void print_generic_status_error() { + printf("Error while parsing file\n"); + printf("Processes may be monitored incorrectly\n"); } -void checkStatus(FILE *file, int *currRealMem, int *peakRealMem, - int *currVirtMem, int *peakVirtMem) -{ +static void check_status(FILE* file, int* curr_real_mem, int* peak_real_mem, + int* curr_virt_mem, int* peak_virt_mem) { - char result[BUFFER_SIZE]; - bzero(result, sizeof(result)); + char result[BUFFER_SIZE]; + memset(result, 0, sizeof result); - while (fscanf(file, " %1023s", result) == 1) - { - if (strcmp(result, "VmRSS:") == 0) - { - if (fscanf(file, " %d", currRealMem) == EOF) - { - printGenericStatusError(); - return; - } - } - - if (strcmp(result, "VmHWM:") == 0) - { - if (fscanf(file, " %d", peakRealMem) == EOF) - { - printGenericStatusError(); - return; - } - } - - if (strcmp(result, "VmSize:") == 0) - { - if (fscanf(file, " %d", currVirtMem) == EOF) - { - printGenericStatusError(); - return; - } - } - - if (strcmp(result, "VmPeak:") == 0) - { - if (fscanf(file, " %d", peakVirtMem) == EOF) - { - printGenericStatusError(); - return; - } - } + while (fscanf(file, " %1023s", result) == 1) { + if (strcmp(result, "VmRSS:") == 0) { + if (fscanf(file, " %d", curr_real_mem) == EOF) { + print_generic_status_error(); + return; + } } + + if (strcmp(result, "VmHWM:") == 0) { + if (fscanf(file, " %d", peak_real_mem) == EOF) { + print_generic_status_error(); + return; + } + } + + if (strcmp(result, "VmSize:") == 0) { + if (fscanf(file, " %d", curr_virt_mem) == EOF) { + print_generic_status_error(); + return; + } + } + + if (strcmp(result, "VmPeak:") == 0) { + if (fscanf(file, " %d", peak_virt_mem) == EOF) { + print_generic_status_error(); + return; + } + } + } } -int isProcessWild(int currRealMem, int peakRealMem, - int currVirtMem, int peakVirtMem, int ID) -{ - if (currRealMem <= MAX_MEMORY) - { - return 0; - } +static int is_process_wild(int curr_real_mem, int peak_real_mem, + int curr_virt_mem, int peak_virt_mem, int id) { + if (curr_real_mem <= MAX_MEMORY) { + return 0; + } - // Sends a polite request to terminate - printf("Terminating process: %d. Too much memory!\n", ID); - int result = kill(ID, SIGTERM); - if (result) - { - printf("Error while terminating process: %d\n", ID); - printf("Error message: %s\n", strerror(errno)); - } + // Sends a polite request to terminate + printf("Terminating process: %d. Memory: %d\n", id, curr_real_mem); + int result = kill(id, SIGTERM); - // Logs - FILE *fp; - fp = fopen("Diavolo.txt", "a"); - if (fp == NULL) - { - perror("popen"); - exit(EXIT_FAILURE); - } - - printTimeStamp(fp); - fprintf(fp, "WARNING: Exceeded %d KiB of Real Memory for process ID: %d\n", MAX_MEMORY, ID); - fprintf(fp, "Process ID: %d\ncurrRealMem:%d KiB\npeakRealMem:%d KiB\ncurrVirtMem:%d KiB\npeakVirtMem:%d KiB\n", ID, currRealMem, peakRealMem, currVirtMem, peakVirtMem); - fclose(fp); + // Logs + FILE* fp; + fp = fopen("log.txt", "a"); + if (fp == NULL) { + printf("Error while opening log.txt\n"); + perror("popen"); return 1; + } + + char time[32]; + get_time_stamp(time); + + fprintf(fp, "\nTimeStamp: %s\n", time); + fprintf(fp, "WARNING: Exceeded %d KiB of Real Memory for process ID: %d\n", + MAX_MEMORY, id); + fprintf(fp, + "Process ID: %d\ncurr_real_mem:%d KiB\npeak_real_mem:%d " + "KiB\ncurr_virt_mem:%d KiB\npeak_virt_mem:%d KiB\n", + id, curr_real_mem, peak_real_mem, curr_virt_mem, peak_virt_mem); + + if (result != 0) { + fprintf(fp, "Error while terminating process: %d\n", id); + fprintf(fp, "Error message: %s\n", strerror(errno)); + } + + fclose(fp); + + return 1; } -static int processID[MAX_TRACK_SIZE] = {0}; +struct process_monitor { + int id; + int active; +}; -void setup(const char *pid) -{ - char *command = va("pgrep %s", pid); - FILE *file = popen(command, "r"); - if (file == NULL) - { - perror("popen"); - exit(EXIT_FAILURE); - } +static struct process_monitor processes[MAX_TRACK_SIZE]; - char result[BUFFER_SIZE]; - bzero(result, sizeof(result)); - int i = 0; +int setup(const char* pid) { + char* command = va("pgrep %s", pid); + FILE* file = popen(command, "r"); + if (file == NULL) { + perror("popen"); + return 1; + } - while (fgets(result, BUFFER_SIZE, file)) - { - printf("Process ID: %s", result); - processID[i] = atoi(result); - i++; + char result[BUFFER_SIZE]; + memset(result, 0, sizeof result); + int i = 0; - if (i >= MAX_TRACK_SIZE) - { - printf("Too many processes found\n"); - break; - } - } + memset(&processes, 0, sizeof(struct process_monitor)); + while (fgets(result, BUFFER_SIZE, file) && i < MAX_TRACK_SIZE) { + printf("Process ID: %s", result); + processes[i].id = atoi(result); + processes[i].active = 1; - if (i == 0) - { - printf("No process was found\n"); - exit(EXIT_SUCCESS); - } + ++i; + } + if (i == 0) { + printf("No process was found\n"); pclose(file); + return 1; + } + + return 0; } -void analyse() -{ - int i; - FILE *status; - int currRealMem = 0, peakRealMem = 0, currVirtMem = 0, peakVirtMem = 0; +int analyse() { + int i; + FILE* status; + int curr_real_mem = 0, peak_real_mem = 0, curr_virt_mem = 0, + peak_virt_mem = 0; - for (i = 0; i < MAX_TRACK_SIZE && processID[i] != 0; i++) - { - char *command = va("cat /proc/%d/status", processID[i]); - status = popen(command, "r"); - if (status == NULL) - { - perror("popen"); - exit(EXIT_FAILURE); - } - - checkStatus(status, &currRealMem, &peakRealMem, &currVirtMem, &peakVirtMem); - if (isProcessWild(currRealMem, peakRealMem, currVirtMem, peakVirtMem, processID[i])) - { - processID[i] = 0; - } - - pclose(status); - currRealMem = 0, peakRealMem = 0, currVirtMem = 0, peakVirtMem = 0; + for (i = 0; i < MAX_TRACK_SIZE && processes[i].active == 1; ++i) { + char* command = va("cat /proc/%d/status", processes[i].id); + status = popen(command, "r"); + if (status == NULL) { + perror("popen"); + pclose(status); + return 1; } + +#ifdef _DEBUG + printf("Checking %d\n", processes[i].id); +#endif + + check_status(status, &curr_real_mem, &peak_real_mem, &curr_virt_mem, + &peak_virt_mem); + if (is_process_wild(curr_real_mem, peak_real_mem, curr_virt_mem, + peak_virt_mem, processes[i].id)) { + processes[i].active = 0; + } + + pclose(status); + curr_real_mem = 0, peak_real_mem = 0, curr_virt_mem = 0, peak_virt_mem = 0; + } + + return 0; } diff --git a/monitor.h b/monitor.h index a068eb7..298a64c 100644 --- a/monitor.h +++ b/monitor.h @@ -1,7 +1,7 @@ #ifndef MONITOR_H #define MONITOR_H -void setup(const char *pid); -void analyse(); +int setup(const char* pid); +int analyse(); #endif /* MONITOR_H */ diff --git a/utils.c b/utils.c index 7dcadb4..90b13b5 100644 --- a/utils.c +++ b/utils.c @@ -1,21 +1,29 @@ -#include "common.h" +#include +#include +#include + #include "utils.h" #define VA_BUFFER_COUNT 4 #define VA_BUFFER_SIZE 4096 -char *va(const char *fmt, ...) -{ - static char g_vaBuffer[VA_BUFFER_COUNT][VA_BUFFER_SIZE]; - static int g_vaNextBufferIndex = 0; +thread_local struct { + char va_string[VA_BUFFER_COUNT][VA_BUFFER_SIZE]; + int index; +} va_info_t; - va_list ap; - char *dest = &g_vaBuffer[g_vaNextBufferIndex][0]; - bzero(dest, VA_BUFFER_SIZE); - g_vaNextBufferIndex = (g_vaNextBufferIndex + 1) % VA_BUFFER_COUNT; - va_start(ap, fmt); - vsnprintf(dest, VA_BUFFER_SIZE, fmt, ap); - va_end(ap); +char* va(const char* fmt, ...) { + va_list ap; - return dest; + int index = va_info_t.index; + va_info_t.index = (va_info_t.index + 1) % VA_BUFFER_COUNT; + char* buf = va_info_t.va_string[index]; + + va_start(ap, fmt); + vsnprintf(buf, VA_BUFFER_SIZE, fmt, ap); + va_end(ap); + + buf[VA_BUFFER_SIZE - 1] = '\0'; + + return buf; } diff --git a/utils.h b/utils.h index 6ef62d4..dfdd640 100644 --- a/utils.h +++ b/utils.h @@ -1,6 +1,6 @@ #ifndef UTILS_H #define UTILS_H -char *va(const char *fmt, ...); +char* va(const char* fmt, ...); #endif /* UTILS_H */