/* * */ #include #include #include #include #include #include #include #include #define STRING_MAX (512) void handle_oom(void) { printf("notification received\n"); } int wait_oom_notifier(int eventfd_fd, void (*handler)(void)) { uint64_t ret; int err; for (;;) { err = read(eventfd_fd, &ret, sizeof(ret)); if (err != sizeof(ret)) { fprintf(stderr, "read()\n"); return err; } handler(); } } int register_oom_notifier(const char *memcg) { char path[PATH_MAX]; char control_string[STRING_MAX]; int event_control_fd; int control_fd; int eventfd_fd; int err = 0; err = snprintf(path, PATH_MAX, "%s/memory.oom_control", memcg); if (err < 0) { fprintf(stderr, "snprintf()\n"); goto out; } control_fd = open(path, O_RDONLY); if (control_fd == -1) { fprintf(stderr, "open(): %d\n", errno); err = errno; goto out; } eventfd_fd = eventfd(0, 0); if (eventfd_fd == -1) { fprintf(stderr, "eventfd(): %d\n", errno); err = errno; goto out_close_control; } err = snprintf(control_string, STRING_MAX, "%d %d", eventfd_fd, control_fd); if (err < 0) { fprintf(stderr, "snprintf()\n"); goto out_close_eventfd; } err = snprintf(path, PATH_MAX, "%s/cgroup.event_control", memcg); if (err < 0) { fprintf(stderr, "snprintf()\n"); goto out_close_eventfd; } event_control_fd = open(path, O_WRONLY); if (event_control_fd == 1) { fprintf(stderr, "open(): %d\n", errno); err = errno; goto out_close_eventfd; } write(event_control_fd, control_string, strlen(control_string)); close(event_control_fd); return eventfd_fd; out_close_eventfd: close(eventfd_fd); out_close_control: close(control_fd); out: return err; } int main(int argc, char **argv) { int eventfd_fd; int err = 0; if (argc != 2) { fprintf(stderr, "usage: %s \n", argv[0]); return -1; } err = mlockall(MCL_FUTURE); if (err) { fprintf(stderr, "%d\n", errno); return -1; } eventfd_fd = register_oom_notifier(argv[1]); if (eventfd_fd < 0) { fprintf(stderr, "%d\n", err); goto out; } err = wait_oom_notifier(eventfd_fd, handle_oom); if (err) { fprintf(stderr, "wait_oom_notifier()\n"); goto out; } out: munlockall(); return err; }