github.com/cloudfoundry-attic/garden-linux@v0.333.2-candidate/linux_backend/src/oom/oom.c (about) 1 #include <assert.h> 2 #include <errno.h> 3 #include <fcntl.h> 4 #include <signal.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <sys/eventfd.h> 9 #include <sys/param.h> 10 #include <sys/prctl.h> 11 #include <sys/stat.h> 12 #include <sys/time.h> 13 #include <sys/types.h> 14 #include <unistd.h> 15 16 /* `detect_oom` returns zero when OOM was detected, non-zero otherwise. */ 17 int detect_oom(int event_fd, const char *event_control_path) { 18 fd_set rfds; 19 int rv; 20 21 FD_ZERO(&rfds); 22 23 /* Stick around for read on eventfd */ 24 FD_SET(event_fd, &rfds); 25 26 do { 27 rv = select(event_fd + 1, &rfds, NULL, NULL, NULL); 28 } while(rv == -1 && errno == EINTR); 29 30 /* Return if something other than an OOM happened */ 31 if (!FD_ISSET(event_fd, &rfds)) { 32 return -1; 33 } 34 35 uint64_t result; 36 37 do { 38 rv = read(event_fd, &result, sizeof(result)); 39 } while (rv == -1 && errno == EINTR); 40 41 if (rv == -1) { 42 perror("read"); 43 return -1; 44 } 45 46 assert(rv == sizeof(result)); 47 48 /* Check if the event_fd triggered because the cgroup was removed */ 49 rv = access(event_control_path, W_OK); 50 if (rv == -1 && errno == ENOENT) { 51 perror("access"); 52 return -1; 53 } 54 55 if (rv == -1) { 56 perror("access"); 57 return -1; 58 } 59 60 /* Read from event_fd, and cgroup is present */ 61 return 0; 62 } 63 64 int main(int argc, char **argv) { 65 int event_fd = -1; 66 char oom_control_path[PATH_MAX]; 67 size_t oom_control_path_len; 68 int oom_control_fd = -1; 69 char event_control_path[PATH_MAX]; 70 size_t event_control_path_len; 71 int event_control_fd = -1; 72 char line[LINE_MAX]; 73 size_t line_len; 74 int rv; 75 76 if (argc != 2) { 77 fprintf(stderr, "Usage: %s <path to cgroup>\n", argv[0]); 78 return 1; 79 } 80 81 /* Die when parent dies */ 82 rv = prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); 83 if (rv == -1) { 84 perror("prctl"); 85 return 1; 86 } 87 88 /* Open event fd */ 89 event_fd = eventfd(0, 0); 90 if (event_fd == -1) { 91 perror("eventfd"); 92 return 1; 93 } 94 95 /* Open oom control file */ 96 oom_control_path_len = snprintf(oom_control_path, sizeof(oom_control_path), "%s/memory.oom_control", argv[1]); 97 assert(oom_control_path_len < sizeof(oom_control_path)); 98 99 oom_control_fd = open(oom_control_path, O_RDONLY); 100 if (oom_control_fd == -1) { 101 perror("open"); 102 return 1; 103 } 104 105 /* Open event control file */ 106 event_control_path_len = snprintf(event_control_path, sizeof(event_control_path), "%s/cgroup.event_control", argv[1]); 107 assert(event_control_path_len < sizeof(event_control_path)); 108 109 event_control_fd = open(event_control_path, O_WRONLY); 110 if (event_control_fd == -1) { 111 perror("open"); 112 return 1; 113 } 114 115 /* Write event fd and oom control fd to event control fd */ 116 line_len = snprintf(line, sizeof(line), "%d %d\n", event_fd, oom_control_fd); 117 assert(line_len < sizeof(line)); 118 119 rv = write(event_control_fd, line, line_len); 120 if (rv == -1) { 121 perror("write"); 122 return 1; 123 } 124 125 rv = detect_oom(event_fd, event_control_path); 126 if (rv == -1) { 127 return 1; 128 } 129 130 /* OOM happened */ 131 return 0; 132 }