]>
Commit | Line | Data |
---|---|---|
1d8fd973 KS |
1 | /* |
2 | * cgroup_event_listener.c - Simple listener of cgroup events | |
3 | * | |
4 | * Copyright (C) Kirill A. Shutemov <kirill@shutemov.name> | |
5 | */ | |
6 | ||
7 | #include <assert.h> | |
8 | #include <errno.h> | |
9 | #include <fcntl.h> | |
10 | #include <libgen.h> | |
11 | #include <limits.h> | |
12 | #include <stdio.h> | |
13 | #include <string.h> | |
14 | #include <unistd.h> | |
15 | ||
16 | #include <sys/eventfd.h> | |
17 | ||
18 | #define USAGE_STR "Usage: cgroup_event_listener <path-to-control-file> <args>\n" | |
19 | ||
20 | int main(int argc, char **argv) | |
21 | { | |
22 | int efd = -1; | |
23 | int cfd = -1; | |
24 | int event_control = -1; | |
25 | char event_control_path[PATH_MAX]; | |
26 | char line[LINE_MAX]; | |
27 | int ret; | |
28 | ||
29 | if (argc != 3) { | |
30 | fputs(USAGE_STR, stderr); | |
31 | return 1; | |
32 | } | |
33 | ||
34 | cfd = open(argv[1], O_RDONLY); | |
35 | if (cfd == -1) { | |
36 | fprintf(stderr, "Cannot open %s: %s\n", argv[1], | |
37 | strerror(errno)); | |
38 | goto out; | |
39 | } | |
40 | ||
41 | ret = snprintf(event_control_path, PATH_MAX, "%s/cgroup.event_control", | |
42 | dirname(argv[1])); | |
43 | if (ret >= PATH_MAX) { | |
44 | fputs("Path to cgroup.event_control is too long\n", stderr); | |
45 | goto out; | |
46 | } | |
47 | ||
48 | event_control = open(event_control_path, O_WRONLY); | |
49 | if (event_control == -1) { | |
50 | fprintf(stderr, "Cannot open %s: %s\n", event_control_path, | |
51 | strerror(errno)); | |
52 | goto out; | |
53 | } | |
54 | ||
55 | efd = eventfd(0, 0); | |
56 | if (efd == -1) { | |
57 | perror("eventfd() failed"); | |
58 | goto out; | |
59 | } | |
60 | ||
61 | ret = snprintf(line, LINE_MAX, "%d %d %s", efd, cfd, argv[2]); | |
62 | if (ret >= LINE_MAX) { | |
63 | fputs("Arguments string is too long\n", stderr); | |
64 | goto out; | |
65 | } | |
66 | ||
67 | ret = write(event_control, line, strlen(line) + 1); | |
68 | if (ret == -1) { | |
69 | perror("Cannot write to cgroup.event_control"); | |
70 | goto out; | |
71 | } | |
72 | ||
73 | while (1) { | |
74 | uint64_t result; | |
75 | ||
76 | ret = read(efd, &result, sizeof(result)); | |
77 | if (ret == -1) { | |
78 | if (errno == EINTR) | |
79 | continue; | |
80 | perror("Cannot read from eventfd"); | |
81 | break; | |
82 | } | |
83 | assert(ret == sizeof(result)); | |
84 | ||
85 | ret = access(event_control_path, W_OK); | |
86 | if ((ret == -1) && (errno == ENOENT)) { | |
87 | puts("The cgroup seems to have removed."); | |
88 | ret = 0; | |
89 | break; | |
90 | } | |
91 | ||
92 | if (ret == -1) { | |
93 | perror("cgroup.event_control " | |
b595076a | 94 | "is not accessible any more"); |
1d8fd973 KS |
95 | break; |
96 | } | |
97 | ||
98 | printf("%s %s: crossed\n", argv[1], argv[2]); | |
99 | } | |
100 | ||
101 | out: | |
102 | if (efd >= 0) | |
103 | close(efd); | |
104 | if (event_control >= 0) | |
105 | close(event_control); | |
106 | if (cfd >= 0) | |
107 | close(cfd); | |
108 | ||
109 | return (ret != 0); | |
110 | } |