Fixed handling of cgroup directories with various names by ensuring correct generation of the `cgroup.events` file path
126 lines
2.9 KiB
C
126 lines
2.9 KiB
C
#include <sys/inotify.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <fcntl.h>
|
|
#include <dirent.h>
|
|
|
|
#define BUFFER_LEN (1024 * (sizeof(struct inotify_event) + 16))
|
|
|
|
void handle_cgroup_event(const char *event_file) {
|
|
char buffer[256];
|
|
int fd = open(event_file, O_RDONLY);
|
|
if(fd < 0) {
|
|
return;
|
|
}
|
|
|
|
ssize_t bytesRead = read(fd, buffer, sizeof(buffer) - 1);
|
|
close(fd);
|
|
if(bytesRead < 0) {
|
|
return;
|
|
}
|
|
|
|
buffer[bytesRead] = '\0';
|
|
|
|
if(strstr(buffer, "populated 0")) {
|
|
char dir[1024];
|
|
strcpy(dir, event_file);
|
|
*strrchr(dir, '/') = '\0';
|
|
rmdir(dir);
|
|
}
|
|
}
|
|
|
|
void scan_and_clean_cgroup_directory(const char *dir) {
|
|
DIR *d = opendir(dir);
|
|
if (!d) {
|
|
return;
|
|
}
|
|
|
|
struct dirent *entry;
|
|
while ((entry = readdir(d)) != NULL) {
|
|
if (entry->d_type == DT_DIR) {
|
|
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
|
|
continue;
|
|
}
|
|
|
|
char subdir[1024];
|
|
snprintf(subdir, sizeof(subdir), "%s/%s/cgroup.events", dir, entry->d_name);
|
|
handle_cgroup_event(subdir);
|
|
}
|
|
}
|
|
|
|
closedir(d);
|
|
}
|
|
|
|
void monitor_directory(const char *dir) {
|
|
int inotify_fd = inotify_init();
|
|
if(inotify_fd < 0) {
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
int wd = inotify_add_watch(inotify_fd, dir, IN_CREATE);
|
|
if(wd < 0) {
|
|
close(inotify_fd);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
char buffer[BUFFER_LEN];
|
|
while(1) {
|
|
ssize_t length = read(inotify_fd, buffer, BUFFER_LEN);
|
|
if(length < 0) {
|
|
close(inotify_fd);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
char *ptr;
|
|
for(ptr = buffer; ptr < buffer + length; ptr += sizeof(struct inotify_event) + ((struct inotify_event *)ptr)->len) {
|
|
struct inotify_event *event = (struct inotify_event *)ptr;
|
|
if(event->mask & IN_CREATE && event->mask & IN_ISDIR) {
|
|
char cgroup_event_path[1024];
|
|
snprintf(cgroup_event_path, sizeof(cgroup_event_path), "%s/%s/cgroup.events", dir, event->name);
|
|
|
|
sleep(1);
|
|
|
|
int cgroup_event_wd = inotify_add_watch(inotify_fd, cgroup_event_path, IN_MODIFY);
|
|
if(cgroup_event_wd >= 0) {
|
|
handle_cgroup_event(cgroup_event_path);
|
|
}
|
|
} else if(event->mask & IN_MODIFY) {
|
|
char cgroup_event_path[1024];
|
|
snprintf(cgroup_event_path, sizeof(cgroup_event_path), "%s/%s/cgroup.events", dir, event->name);
|
|
handle_cgroup_event(cgroup_event_path);
|
|
}
|
|
}
|
|
}
|
|
|
|
close(inotify_fd);
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
const char *cgroup_dir = "/sys/fs/cgroup";
|
|
int run_as_daemon = (argc > 1 && strcmp(argv[1], "--daemon") == 0);
|
|
|
|
scan_and_clean_cgroup_directory(cgroup_dir);
|
|
|
|
if(run_as_daemon) {
|
|
if(fork() > 0) exit(EXIT_SUCCESS);
|
|
if(setsid() < 0) exit(EXIT_FAILURE);
|
|
if(fork() > 0) exit(EXIT_SUCCESS);
|
|
|
|
chdir("/");
|
|
for(int x = sysconf(_SC_OPEN_MAX); x >= 0; x--) {
|
|
close(x);
|
|
}
|
|
|
|
open("/dev/null", O_RDWR);
|
|
dup(0);
|
|
dup(0);
|
|
|
|
monitor_directory(cgroup_dir);
|
|
}
|
|
|
|
return 0;
|
|
}
|