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