Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Greg Thelen and committed by
Tejun Heo
799105d5 92e015b1

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