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  }