chiark / gitweb /
cgroup: after killing cgroup processes, ensure the group is really dead gone. wait...
[elogind.git] / src / cgroup-util.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23 #include <unistd.h>
24 #include <signal.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <dirent.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30
31 #include "cgroup-util.h"
32 #include "log.h"
33 #include "set.h"
34 #include "macro.h"
35 #include "util.h"
36
37 int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) {
38         char *fs;
39         int r;
40         FILE *f;
41
42         assert(controller);
43         assert(path);
44         assert(_f);
45
46         if ((r = cg_get_path(controller, path, "cgroup.procs", &fs)) < 0)
47                 return r;
48
49         f = fopen(fs, "re");
50         free(fs);
51
52         if (!f)
53                 return -errno;
54
55         *_f = f;
56         return 0;
57 }
58
59 int cg_enumerate_tasks(const char *controller, const char *path, FILE **_f) {
60         char *fs;
61         int r;
62         FILE *f;
63
64         assert(controller);
65         assert(path);
66         assert(_f);
67
68         if ((r = cg_get_path(controller, path, "tasks", &fs)) < 0)
69                 return r;
70
71         f = fopen(fs, "re");
72         free(fs);
73
74         if (!f)
75                 return -errno;
76
77         *_f = f;
78         return 0;
79 }
80
81 int cg_read_pid(FILE *f, pid_t *_pid) {
82         unsigned long ul;
83
84         /* Note that the cgroup.procs might contain duplicates! See
85          * cgroups.txt for details. */
86
87         errno = 0;
88         if (fscanf(f, "%lu", &ul) != 1) {
89
90                 if (feof(f))
91                         return 0;
92
93                 return errno ? -errno : -EIO;
94         }
95
96         if (ul <= 0)
97                 return -EIO;
98
99         *_pid = (pid_t) ul;
100         return 1;
101 }
102
103 int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d) {
104         char *fs;
105         int r;
106         DIR *d;
107
108         assert(controller);
109         assert(path);
110         assert(_d);
111
112         /* This is not recursive! */
113
114         if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
115                 return r;
116
117         d = opendir(fs);
118         free(fs);
119
120         if (!d)
121                 return -errno;
122
123         *_d = d;
124         return 0;
125 }
126
127 int cg_read_subgroup(DIR *d, char **fn) {
128         struct dirent *de;
129
130         assert(d);
131
132         errno = 0;
133         while ((de = readdir(d))) {
134                 char *b;
135
136                 if (de->d_type != DT_DIR)
137                         continue;
138
139                 if (streq(de->d_name, ".") ||
140                     streq(de->d_name, ".."))
141                         continue;
142
143                 if (!(b = strdup(de->d_name)))
144                         return -ENOMEM;
145
146                 *fn = b;
147                 return 1;
148         }
149
150         if (errno)
151                 return -errno;
152
153         return 0;
154 }
155
156 int cg_rmdir(const char *controller, const char *path) {
157         char *p;
158         int r;
159
160         if ((r = cg_get_path(controller, path, NULL, &p)) < 0)
161                 return r;
162
163         r = rmdir(p);
164         free(p);
165
166         return r < 0 ? -errno : 0;
167 }
168
169 int cg_kill(const char *controller, const char *path, int sig, bool ignore_self, Set *s) {
170         bool done = false;
171         int r, ret = 0;
172         pid_t my_pid;
173         FILE *f = NULL;
174         Set *allocated_set = NULL;
175
176         assert(controller);
177         assert(path);
178         assert(sig >= 0);
179
180         /* This goes through the tasks list and kills them all. This
181          * is repeated until no further processes are added to the
182          * tasks list, to properly handle forking processes */
183
184         if (!s)
185                 if (!(s = allocated_set = set_new(trivial_hash_func, trivial_compare_func)))
186                         return -ENOMEM;
187
188         my_pid = getpid();
189
190         do {
191                 pid_t pid;
192                 done = true;
193
194                 if ((r = cg_enumerate_processes(controller, path, &f)) < 0) {
195                         if (ret >= 0 && r != -ENOENT)
196                                 ret = r;
197
198                         goto finish;
199                 }
200
201                 while ((r = cg_read_pid(f, &pid)) > 0) {
202
203                         if (pid == my_pid && ignore_self)
204                                 continue;
205
206                         if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
207                                 continue;
208
209                         /* If we haven't killed this process yet, kill
210                          * it */
211                         if (kill(pid, sig) < 0) {
212                                 if (ret >= 0 && errno != ESRCH)
213                                         ret = -errno;
214                         } else if (ret == 0)
215                                 ret = 1;
216
217                         done = false;
218
219                         if ((r = set_put(s, LONG_TO_PTR(pid))) < 0) {
220                                 if (ret >= 0)
221                                         ret = r;
222
223                                 goto finish;
224                         }
225                 }
226
227                 if (r < 0) {
228                         if (ret >= 0)
229                                 ret = r;
230
231                         goto finish;
232                 }
233
234                 fclose(f);
235                 f = NULL;
236
237                 /* To avoid racing against processes which fork
238                  * quicker than we can kill them we repeat this until
239                  * no new pids need to be killed. */
240
241         } while (!done);
242
243 finish:
244         if (allocated_set)
245                 set_free(allocated_set);
246
247         if (f)
248                 fclose(f);
249
250         return ret;
251 }
252
253 int cg_kill_recursive(const char *controller, const char *path, int sig, bool ignore_self, bool rem, Set *s) {
254         int r, ret = 0;
255         DIR *d = NULL;
256         char *fn;
257         Set *allocated_set = NULL;
258
259         assert(path);
260         assert(controller);
261         assert(sig >= 0);
262
263         if (!s)
264                 if (!(s = allocated_set = set_new(trivial_hash_func, trivial_compare_func)))
265                         return -ENOMEM;
266
267         ret = cg_kill(controller, path, sig, ignore_self, s);
268
269         if ((r = cg_enumerate_subgroups(controller, path, &d)) < 0) {
270                 if (ret >= 0 && r != -ENOENT)
271                         ret = r;
272
273                 goto finish;
274         }
275
276         while ((r = cg_read_subgroup(d, &fn)) > 0) {
277                 char *p = NULL;
278
279                 r = asprintf(&p, "%s/%s", path, fn);
280                 free(fn);
281
282                 if (r < 0) {
283                         if (ret >= 0)
284                                 ret = -ENOMEM;
285
286                         goto finish;
287                 }
288
289                 r = cg_kill_recursive(controller, p, sig, ignore_self, rem, s);
290                 free(p);
291
292                 if (r != 0 && ret >= 0)
293                         ret = r;
294         }
295
296         if (r < 0 && ret >= 0)
297                 ret = r;
298
299         if (rem)
300                 if ((r = cg_rmdir(controller, path)) < 0) {
301                         if (ret >= 0 &&
302                             r != -ENOENT &&
303                             r != -EBUSY)
304                                 ret = r;
305                 }
306
307 finish:
308         if (d)
309                 closedir(d);
310
311         if (allocated_set)
312                 set_free(allocated_set);
313
314         return ret;
315 }
316
317 int cg_kill_recursive_and_wait(const char *controller, const char *path, bool rem) {
318         unsigned i;
319
320         assert(path);
321         assert(controller);
322
323         /* This safely kills all processes; first it sends a SIGTERM,
324          * then checks 8 times after 200ms whether the group is now
325          * empty, then kills everything that is left with SIGKILL and
326          * finally checks 5 times after 200ms each whether the group
327          * is finally empty. */
328
329         for (i = 0; i < 15; i++) {
330                 int sig, r;
331
332                 if (i <= 0)
333                         sig = SIGTERM;
334                 else if (i == 9)
335                         sig = SIGKILL;
336                 else
337                         sig = 0;
338
339                 if ((r = cg_kill_recursive(controller, path, sig, true, rem, NULL)) <= 0)
340                         return r;
341
342                 usleep(200 * USEC_PER_MSEC);
343         }
344
345         return 0;
346 }
347
348 int cg_migrate(const char *controller, const char *from, const char *to, bool ignore_self) {
349         bool done = false;
350         Set *s;
351         int r, ret = 0;
352         pid_t my_pid;
353         FILE *f = NULL;
354
355         assert(controller);
356         assert(from);
357         assert(to);
358
359         if (!(s = set_new(trivial_hash_func, trivial_compare_func)))
360                 return -ENOMEM;
361
362         my_pid = getpid();
363
364         do {
365                 pid_t pid;
366                 done = true;
367
368                 if ((r = cg_enumerate_tasks(controller, from, &f)) < 0) {
369                         if (ret >= 0 && r != -ENOENT)
370                                 ret = r;
371
372                         goto finish;
373                 }
374
375                 while ((r = cg_read_pid(f, &pid)) > 0) {
376
377                         /* This might do weird stuff if we aren't a
378                          * single-threaded program. However, we
379                          * luckily know we are not */
380                         if (pid == my_pid && ignore_self)
381                                 continue;
382
383                         if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
384                                 continue;
385
386                         if ((r = cg_attach(controller, to, pid)) < 0) {
387                                 if (ret >= 0 && r != -ESRCH)
388                                         ret = r;
389                         } else if (ret == 0)
390                                 ret = 1;
391
392                         done = false;
393
394                         if ((r = set_put(s, LONG_TO_PTR(pid))) < 0) {
395                                 if (ret >= 0)
396                                         ret = r;
397
398                                 goto finish;
399                         }
400                 }
401
402                 if (r < 0) {
403                         if (ret >= 0)
404                                 ret = r;
405
406                         goto finish;
407                 }
408
409                 fclose(f);
410                 f = NULL;
411
412         } while (!done);
413
414 finish:
415         set_free(s);
416
417         if (f)
418                 fclose(f);
419
420         return ret;
421 }
422
423 int cg_migrate_recursive(const char *controller, const char *from, const char *to, bool ignore_self, bool rem) {
424         int r, ret = 0;
425         DIR *d = NULL;
426         char *fn;
427
428         assert(controller);
429         assert(from);
430         assert(to);
431
432         ret = cg_migrate(controller, from, to, ignore_self);
433
434         if ((r = cg_enumerate_subgroups(controller, from, &d)) < 0) {
435                 if (ret >= 0 && r != -ENOENT)
436                         ret = r;
437                 goto finish;
438         }
439
440         while ((r = cg_read_subgroup(d, &fn)) > 0) {
441                 char *p = NULL;
442
443                 r = asprintf(&p, "%s/%s", from, fn);
444                 free(fn);
445
446                 if (r < 0) {
447                         if (ret >= 0)
448                                 ret = -ENOMEM;
449
450                         goto finish;
451                 }
452
453                 r = cg_migrate_recursive(controller, p, to, ignore_self, rem);
454                 free(p);
455
456                 if (r != 0 && ret >= 0)
457                         ret = r;
458         }
459
460         if (r < 0 && ret >= 0)
461                 ret = r;
462
463         if (rem)
464                 if ((r = cg_rmdir(controller, from)) < 0) {
465                         if (ret >= 0 &&
466                             r != -ENOENT &&
467                             r != -EBUSY)
468                                 ret = r;
469                 }
470
471 finish:
472         if (d)
473                 closedir(d);
474
475         return ret;
476 }
477
478 int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) {
479         const char *p;
480         char *mp;
481         int r;
482
483         assert(controller);
484         assert(fs);
485
486         /* This is a very minimal lookup from controller names to
487          * paths. Since we have mounted most hierarchies ourselves
488          * should be kinda safe, but eventually we might want to
489          * extend this to have a fallback to actually check
490          * /proc/mounts. Might need caching then. */
491
492         if (streq(controller, SYSTEMD_CGROUP_CONTROLLER))
493                 p = "systemd";
494         else if (startswith(controller, "name="))
495                 p = controller + 5;
496         else
497                 p = controller;
498
499         if (asprintf(&mp, "/sys/fs/cgroup/%s", p) < 0)
500                 return -ENOMEM;
501
502         if ((r = path_is_mount_point(mp)) <= 0) {
503                 free(mp);
504                 return r < 0 ? r : -ENOENT;
505         }
506
507         if (path && suffix)
508                 r = asprintf(fs, "%s/%s/%s", mp, path, suffix);
509         else if (path)
510                 r = asprintf(fs, "%s/%s", mp, path);
511         else if (suffix)
512                 r = asprintf(fs, "%s/%s", mp, suffix);
513         else {
514                 path_kill_slashes(mp);
515                 *fs = mp;
516                 return 0;
517         }
518
519         free(mp);
520         path_kill_slashes(*fs);
521         return r < 0 ? -ENOMEM : 0;
522 }
523
524 int cg_trim(const char *controller, const char *path, bool delete_root) {
525         char *fs;
526         int r;
527
528         assert(controller);
529         assert(path);
530
531         if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
532                 return r;
533
534         r = rm_rf(fs, true, delete_root);
535         free(fs);
536
537         return r == -ENOENT ? 0 : r;
538 }
539
540 int cg_delete(const char *controller, const char *path) {
541         char *parent;
542         int r;
543
544         assert(controller);
545         assert(path);
546
547         if ((r = parent_of_path(path, &parent)) < 0)
548                 return r;
549
550         r = cg_migrate_recursive(controller, path, parent, false, true);
551         free(parent);
552
553         return r == -ENOENT ? 0 : r;
554 }
555
556 int cg_create(const char *controller, const char *path) {
557         char *fs;
558         int r;
559
560         assert(controller);
561         assert(path);
562
563         if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
564                 return r;
565
566         r = mkdir_parents(fs, 0755);
567
568         if (r >= 0) {
569                 if (mkdir(fs, 0755) >= 0)
570                         r = 1;
571                 else if (errno == EEXIST)
572                         r = 0;
573                 else
574                         r = -errno;
575         }
576
577         free(fs);
578
579         return r;
580 }
581
582 int cg_attach(const char *controller, const char *path, pid_t pid) {
583         char *fs;
584         int r;
585         char c[32];
586
587         assert(controller);
588         assert(path);
589         assert(pid >= 0);
590
591         if ((r = cg_get_path(controller, path, "tasks", &fs)) < 0)
592                 return r;
593
594         if (pid == 0)
595                 pid = getpid();
596
597         snprintf(c, sizeof(c), "%lu\n", (unsigned long) pid);
598         char_array_0(c);
599
600         r = write_one_line_file(fs, c);
601         free(fs);
602
603         return r;
604 }
605
606 int cg_create_and_attach(const char *controller, const char *path, pid_t pid) {
607         int r, q;
608
609         assert(controller);
610         assert(path);
611         assert(pid >= 0);
612
613         if ((r = cg_create(controller, path)) < 0)
614                 return r;
615
616         if ((q = cg_attach(controller, path, pid)) < 0)
617                 return q;
618
619         /* This does not remove the cgroup on failure */
620
621         return r;
622 }
623
624 int cg_set_group_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid) {
625         char *fs;
626         int r;
627
628         assert(controller);
629         assert(path);
630
631         if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
632                 return r;
633
634         r = chmod_and_chown(fs, mode, uid, gid);
635         free(fs);
636
637         return r;
638 }
639
640 int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid) {
641         char *fs;
642         int r;
643
644         assert(controller);
645         assert(path);
646
647         if ((r = cg_get_path(controller, path, "tasks", &fs)) < 0)
648                 return r;
649
650         r = chmod_and_chown(fs, mode, uid, gid);
651         free(fs);
652
653         return r;
654 }
655
656 int cg_get_by_pid(const char *controller, pid_t pid, char **path) {
657         int r;
658         char *p = NULL;
659         FILE *f;
660         char *fs;
661         size_t cs;
662
663         assert(controller);
664         assert(path);
665         assert(pid >= 0);
666
667         if (pid == 0)
668                 pid = getpid();
669
670         if (asprintf(&fs, "/proc/%lu/cgroup", (unsigned long) pid) < 0)
671                 return -ENOMEM;
672
673         f = fopen(fs, "re");
674         free(fs);
675
676         if (!f)
677                 return errno == ENOENT ? -ESRCH : -errno;
678
679         cs = strlen(controller);
680
681         while (!feof(f)) {
682                 char line[LINE_MAX];
683                 char *l;
684
685                 errno = 0;
686                 if (!(fgets(line, sizeof(line), f))) {
687                         if (feof(f))
688                                 break;
689
690                         r = errno ? -errno : -EIO;
691                         goto finish;
692                 }
693
694                 truncate_nl(line);
695
696                 if (!(l = strchr(line, ':')))
697                         continue;
698
699                 l++;
700                 if (strncmp(l, controller, cs) != 0)
701                         continue;
702
703                 if (l[cs] != ':')
704                         continue;
705
706                 if (!(p = strdup(l + cs + 1))) {
707                         r = -ENOMEM;
708                         goto finish;
709                 }
710
711                 *path = p;
712                 r = 0;
713                 goto finish;
714         }
715
716         r = -ENOENT;
717
718 finish:
719         fclose(f);
720
721         return r;
722 }
723
724 int cg_install_release_agent(const char *controller, const char *agent) {
725         char *fs = NULL, *contents = NULL, *line = NULL, *sc;
726         int r;
727
728         assert(controller);
729         assert(agent);
730
731         if ((r = cg_get_path(controller, NULL, "release_agent", &fs)) < 0)
732                 return r;
733
734         if ((r = read_one_line_file(fs, &contents)) < 0)
735                 goto finish;
736
737         sc = strstrip(contents);
738         if (sc[0] == 0) {
739
740                 if (asprintf(&line, "%s\n", agent) < 0) {
741                         r = -ENOMEM;
742                         goto finish;
743                 }
744
745                 if ((r = write_one_line_file(fs, line)) < 0)
746                         goto finish;
747
748         } else if (!streq(sc, agent)) {
749                 r = -EEXIST;
750                 goto finish;
751         }
752
753         free(fs);
754         fs = NULL;
755         if ((r = cg_get_path(controller, NULL, "notify_on_release", &fs)) < 0)
756                 goto finish;
757
758         free(contents);
759         contents = NULL;
760         if ((r = read_one_line_file(fs, &contents)) < 0)
761                 goto finish;
762
763         sc = strstrip(contents);
764
765         if (streq(sc, "0")) {
766                 if ((r = write_one_line_file(fs, "1\n")) < 0)
767                         goto finish;
768
769                 r = 1;
770         } else if (!streq(sc, "1")) {
771                 r = -EIO;
772                 goto finish;
773         } else
774                 r = 0;
775
776 finish:
777         free(fs);
778         free(contents);
779         free(line);
780
781         return r;
782 }
783
784 int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
785         pid_t pid;
786         int r;
787         FILE *f;
788         bool found = false;
789
790         assert(controller);
791         assert(path);
792
793         if ((r = cg_enumerate_tasks(controller, path, &f)) < 0)
794                 return r == -ENOENT ? 1 : r;
795
796         while ((r = cg_read_pid(f, &pid)) > 0) {
797
798                 if (ignore_self && pid == getpid())
799                         continue;
800
801                 found = true;
802                 break;
803         }
804
805         fclose(f);
806
807         if (r < 0)
808                 return r;
809
810         return !found;
811 }
812
813 int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) {
814         int r;
815         DIR *d = NULL;
816         char *fn;
817
818         assert(controller);
819         assert(path);
820
821         if ((r = cg_is_empty(controller, path, ignore_self)) <= 0)
822                 return r;
823
824         if ((r = cg_enumerate_subgroups(controller, path, &d)) < 0)
825                 return r == -ENOENT ? 1 : r;
826
827         while ((r = cg_read_subgroup(d, &fn)) > 0) {
828                 char *p = NULL;
829
830                 r = asprintf(&p, "%s/%s", path, fn);
831                 free(fn);
832
833                 if (r < 0) {
834                         r = -ENOMEM;
835                         goto finish;
836                 }
837
838                 r = cg_is_empty_recursive(controller, p, ignore_self);
839                 free(p);
840
841                 if (r <= 0)
842                         goto finish;
843         }
844
845         if (r >= 0)
846                 r = 1;
847
848 finish:
849
850         if (d)
851                 closedir(d);
852
853         return r;
854 }
855
856 int cg_split_spec(const char *spec, char **controller, char **path) {
857         const char *e;
858         char *t = NULL, *u = NULL;
859
860         assert(spec);
861         assert(controller || path);
862
863         if (*spec == '/') {
864
865                 if (path) {
866                         if (!(t = strdup(spec)))
867                                 return -ENOMEM;
868
869                         *path = t;
870                 }
871
872                 if (controller)
873                         *controller = NULL;
874
875                 return 0;
876         }
877
878         if (!(e = strchr(spec, ':'))) {
879
880                 if (strchr(spec, '/') || spec[0] == 0)
881                         return -EINVAL;
882
883                 if (controller) {
884                         if (!(t = strdup(spec)))
885                                 return -ENOMEM;
886
887                         *controller = t;
888                 }
889
890                 if (path)
891                         *path = NULL;
892
893                 return 0;
894         }
895
896         if (e[1] != '/' ||
897             e == spec ||
898             memchr(spec, '/', e-spec))
899                 return -EINVAL;
900
901         if (controller)
902                 if (!(t = strndup(spec, e-spec)))
903                         return -ENOMEM;
904
905         if (path)
906                 if (!(u = strdup(e+1))) {
907                         free(t);
908                         return -ENOMEM;
909                 }
910
911         if (controller)
912                 *controller = t;
913
914         if (path)
915                 *path = u;
916
917         return 0;
918 }
919
920 int cg_join_spec(const char *controller, const char *path, char **spec) {
921         assert(controller);
922         assert(path);
923
924         if (!path_is_absolute(path) ||
925             controller[0] == 0 ||
926             strchr(controller, ':') ||
927             strchr(controller, '/'))
928                 return -EINVAL;
929
930         if (asprintf(spec, "%s:%s", controller, path) < 0)
931                 return -ENOMEM;
932
933         return 0;
934 }
935
936 int cg_fix_path(const char *path, char **result) {
937         char *t, *c, *p;
938         int r;
939
940         assert(path);
941         assert(result);
942
943         /* First check if it already is a filesystem path */
944         if (path_is_absolute(path) &&
945             path_startswith(path, "/sys/fs/cgroup") &&
946             access(path, F_OK) >= 0) {
947
948                 if (!(t = strdup(path)))
949                         return -ENOMEM;
950
951                 *result = t;
952                 return 0;
953         }
954
955         /* Otherwise treat it as cg spec */
956         if ((r = cg_split_spec(path, &c, &p)) < 0)
957                 return r;
958
959         r = cg_get_path(c ? c : SYSTEMD_CGROUP_CONTROLLER, p ? p : "/", NULL, result);
960         free(c);
961         free(p);
962
963         return r;
964 }