diff options
author | Greg Thelen <gthelen@google.com> | 2013-01-07 14:50:17 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2013-01-08 13:00:44 -0500 |
commit | 799105d514384b80cbe3182dbcb4ed30aa07e1f5 (patch) | |
tree | a268f0a96609fb09408fb77fd5474489cbb63c76 /tools | |
parent | 92e015b1cfc24e3cb072385f25171b8599cc7ef3 (diff) |
cgroups: fix cgroup_event_listener error handling
The error handling in cgroup_event_listener.c did not correctly deal
with either an error opening either <control_file> or
cgroup.event_control. Due to an uninitialized variable the program
exit code was undefined if either of these opens failed.
This patch simplifies and corrects cgroup_event_listener.c error
handling by:
1. using err*() rather than printf(),exit()
2. depending on process exit to close open files
With this patch failures always return non-zero error.
Signed-off-by: Greg Thelen <gthelen@google.com>
Acked-by: Li Zefan <lizefan@huawei.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/cgroup/cgroup_event_listener.c | 72 |
1 files changed, 22 insertions, 50 deletions
diff --git a/tools/cgroup/cgroup_event_listener.c b/tools/cgroup/cgroup_event_listener.c index 3e082f96dc12..4eb5507205c9 100644 --- a/tools/cgroup/cgroup_event_listener.c +++ b/tools/cgroup/cgroup_event_listener.c | |||
@@ -5,6 +5,7 @@ | |||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <assert.h> | 7 | #include <assert.h> |
8 | #include <err.h> | ||
8 | #include <errno.h> | 9 | #include <errno.h> |
9 | #include <fcntl.h> | 10 | #include <fcntl.h> |
10 | #include <libgen.h> | 11 | #include <libgen.h> |
@@ -15,7 +16,7 @@ | |||
15 | 16 | ||
16 | #include <sys/eventfd.h> | 17 | #include <sys/eventfd.h> |
17 | 18 | ||
18 | #define USAGE_STR "Usage: cgroup_event_listener <path-to-control-file> <args>\n" | 19 | #define USAGE_STR "Usage: cgroup_event_listener <path-to-control-file> <args>" |
19 | 20 | ||
20 | int main(int argc, char **argv) | 21 | int main(int argc, char **argv) |
21 | { | 22 | { |
@@ -26,49 +27,33 @@ int main(int argc, char **argv) | |||
26 | char line[LINE_MAX]; | 27 | char line[LINE_MAX]; |
27 | int ret; | 28 | int ret; |
28 | 29 | ||
29 | if (argc != 3) { | 30 | if (argc != 3) |
30 | fputs(USAGE_STR, stderr); | 31 | errx(1, "%s", USAGE_STR); |
31 | return 1; | ||
32 | } | ||
33 | 32 | ||
34 | cfd = open(argv[1], O_RDONLY); | 33 | cfd = open(argv[1], O_RDONLY); |
35 | if (cfd == -1) { | 34 | if (cfd == -1) |
36 | fprintf(stderr, "Cannot open %s: %s\n", argv[1], | 35 | err(1, "Cannot open %s", argv[1]); |
37 | strerror(errno)); | ||
38 | goto out; | ||
39 | } | ||
40 | 36 | ||
41 | ret = snprintf(event_control_path, PATH_MAX, "%s/cgroup.event_control", | 37 | ret = snprintf(event_control_path, PATH_MAX, "%s/cgroup.event_control", |
42 | dirname(argv[1])); | 38 | dirname(argv[1])); |
43 | if (ret >= PATH_MAX) { | 39 | if (ret >= PATH_MAX) |
44 | fputs("Path to cgroup.event_control is too long\n", stderr); | 40 | errx(1, "Path to cgroup.event_control is too long"); |
45 | goto out; | ||
46 | } | ||
47 | 41 | ||
48 | event_control = open(event_control_path, O_WRONLY); | 42 | event_control = open(event_control_path, O_WRONLY); |
49 | if (event_control == -1) { | 43 | if (event_control == -1) |
50 | fprintf(stderr, "Cannot open %s: %s\n", event_control_path, | 44 | err(1, "Cannot open %s", event_control_path); |
51 | strerror(errno)); | ||
52 | goto out; | ||
53 | } | ||
54 | 45 | ||
55 | efd = eventfd(0, 0); | 46 | efd = eventfd(0, 0); |
56 | if (efd == -1) { | 47 | if (efd == -1) |
57 | perror("eventfd() failed"); | 48 | err(1, "eventfd() failed"); |
58 | goto out; | ||
59 | } | ||
60 | 49 | ||
61 | ret = snprintf(line, LINE_MAX, "%d %d %s", efd, cfd, argv[2]); | 50 | ret = snprintf(line, LINE_MAX, "%d %d %s", efd, cfd, argv[2]); |
62 | if (ret >= LINE_MAX) { | 51 | if (ret >= LINE_MAX) |
63 | fputs("Arguments string is too long\n", stderr); | 52 | errx(1, "Arguments string is too long"); |
64 | goto out; | ||
65 | } | ||
66 | 53 | ||
67 | ret = write(event_control, line, strlen(line) + 1); | 54 | ret = write(event_control, line, strlen(line) + 1); |
68 | if (ret == -1) { | 55 | if (ret == -1) |
69 | perror("Cannot write to cgroup.event_control"); | 56 | err(1, "Cannot write to cgroup.event_control"); |
70 | goto out; | ||
71 | } | ||
72 | 57 | ||
73 | while (1) { | 58 | while (1) { |
74 | uint64_t result; | 59 | uint64_t result; |
@@ -77,34 +62,21 @@ int main(int argc, char **argv) | |||
77 | if (ret == -1) { | 62 | if (ret == -1) { |
78 | if (errno == EINTR) | 63 | if (errno == EINTR) |
79 | continue; | 64 | continue; |
80 | perror("Cannot read from eventfd"); | 65 | err(1, "Cannot read from eventfd"); |
81 | break; | ||
82 | } | 66 | } |
83 | assert(ret == sizeof(result)); | 67 | assert(ret == sizeof(result)); |
84 | 68 | ||
85 | ret = access(event_control_path, W_OK); | 69 | ret = access(event_control_path, W_OK); |
86 | if ((ret == -1) && (errno == ENOENT)) { | 70 | if ((ret == -1) && (errno == ENOENT)) { |
87 | puts("The cgroup seems to have removed."); | 71 | puts("The cgroup seems to have removed."); |
88 | ret = 0; | ||
89 | break; | ||
90 | } | ||
91 | |||
92 | if (ret == -1) { | ||
93 | perror("cgroup.event_control " | ||
94 | "is not accessible any more"); | ||
95 | break; | 72 | break; |
96 | } | 73 | } |
97 | 74 | ||
75 | if (ret == -1) | ||
76 | err(1, "cgroup.event_control is not accessible any more"); | ||
77 | |||
98 | printf("%s %s: crossed\n", argv[1], argv[2]); | 78 | printf("%s %s: crossed\n", argv[1], argv[2]); |
99 | } | 79 | } |
100 | 80 | ||
101 | out: | 81 | return 0; |
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 | } | 82 | } |