chiark / gitweb /
cgroup: kill processes, not tasks and other cgroup changes
[elogind.git] / src / cgroup-util.c
1 /*-*- Mode: C; c-basic-offset: 8 -*-*/
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
28 #include <libcgroup.h>
29
30 #include "cgroup-util.h"
31 #include "log.h"
32 #include "set.h"
33 #include "macro.h"
34 #include "util.h"
35
36 /*
37    Currently, the only remaining functionality from libcgroup we call
38    here is:
39
40    - cgroup_get_subsys_mount_point()
41    - cgroup_walk_tree_begin()/cgroup_walk_tree_next()
42    - cgroup_delete_cgroup_ext()
43  */
44
45 int cg_translate_error(int error, int _errno) {
46
47         switch (error) {
48
49         case ECGROUPNOTCOMPILED:
50         case ECGROUPNOTMOUNTED:
51         case ECGROUPNOTEXIST:
52         case ECGROUPNOTCREATED:
53                 return -ENOENT;
54
55         case ECGINVAL:
56                 return -EINVAL;
57
58         case ECGROUPNOTALLOWED:
59                 return -EPERM;
60
61         case ECGOTHER:
62                 return -_errno;
63         }
64
65         return -EIO;
66 }
67
68 static struct cgroup* cg_new(const char *controller, const char *path) {
69         struct cgroup *cgroup;
70
71         assert(path);
72         assert(controller);
73
74         if (!(cgroup = cgroup_new_cgroup(path)))
75                 return NULL;
76
77         if (!cgroup_add_controller(cgroup, controller)) {
78                 cgroup_free(&cgroup);
79                 return NULL;
80         }
81
82         return cgroup;
83 }
84
85 int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) {
86         char *fs;
87         int r;
88         FILE *f;
89
90         assert(controller);
91         assert(path);
92         assert(_f);
93
94         if ((r = cg_get_path(controller, path, "cgroup.procs", &fs)) < 0)
95                 return r;
96
97         f = fopen(fs, "re");
98         free(fs);
99
100         if (!f)
101                 return -errno;
102
103         *_f = f;
104         return 0;
105 }
106
107 int cg_enumerate_tasks(const char *controller, const char *path, FILE **_f) {
108         char *fs;
109         int r;
110         FILE *f;
111
112         assert(controller);
113         assert(path);
114         assert(_f);
115
116         if ((r = cg_get_path(controller, path, "tasks", &fs)) < 0)
117                 return r;
118
119         f = fopen(fs, "re");
120         free(fs);
121
122         if (!f)
123                 return -errno;
124
125         *_f = f;
126         return 0;
127 }
128
129 int cg_read_pid(FILE *f, pid_t *_pid) {
130         unsigned long ul;
131
132         /* Note that the cgroup.procs might contain duplicates! See
133          * cgroups.txt for details. */
134
135         errno = 0;
136         if (fscanf(f, "%lu", &ul) != 1) {
137
138                 if (feof(f))
139                         return 0;
140
141                 return errno ? -errno : -EIO;
142         }
143
144         if (ul <= 0)
145                 return -EIO;
146
147         *_pid = (pid_t) ul;
148         return 1;
149 }
150
151 int cg_kill(const char *controller, const char *path, int sig, bool ignore_self) {
152         bool killed = false, done = false;
153         Set *s;
154         pid_t my_pid;
155         int r, ret = 0;
156         FILE *f = NULL;
157
158         assert(controller);
159         assert(path);
160         assert(sig >= 0);
161
162         /* This goes through the tasks list and kills them all. This
163          * is repeated until no further processes are added to the
164          * tasks list, to properly handle forking processes */
165
166         if (!(s = set_new(trivial_hash_func, trivial_compare_func)))
167                 return -ENOMEM;
168
169         my_pid = getpid();
170
171         do {
172                 pid_t pid;
173                 done = true;
174
175                 if ((r = cg_enumerate_processes(controller, path, &f)) < 0)
176                         goto finish;
177
178                 while ((r = cg_read_pid(f, &pid)) > 0) {
179
180                         if (pid == my_pid && ignore_self)
181                                 continue;
182
183                         if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
184                                 continue;
185
186                         /* If we haven't killed this process yet, kill
187                          * it */
188                         if (kill(pid, sig) < 0 && errno != ESRCH) {
189                                 if (ret == 0)
190                                         ret = -errno;
191                         }
192
193                         killed = true;
194                         done = false;
195
196                         if ((r = set_put(s, LONG_TO_PTR(pid))) < 0)
197                                 break;
198                 }
199
200                 fclose(f);
201                 f = NULL;
202
203                 /* To avoid racing against processes which fork
204                  * quicker than we can kill them we repeat this until
205                  * no new pids need to be killed. */
206
207         } while (!done && r >= 0);
208
209 finish:
210         set_free(s);
211
212         if (f)
213                 fclose(f);
214
215         if (r < 0)
216                 return r;
217
218         if (ret < 0)
219                 return ret;
220
221         return !!killed;
222 }
223
224 int cg_kill_recursive(const char *controller, const char *path, int sig, bool ignore_self) {
225         struct cgroup_file_info info;
226         int level = 0, r, ret = 0;
227         void *iterator = NULL;
228         bool killed = false;
229
230         assert(path);
231         assert(controller);
232         assert(sig >= 0);
233
234         zero(info);
235
236         r = cgroup_walk_tree_begin(controller, path, 0, &iterator, &info, &level);
237         while (r == 0) {
238                 int k;
239                 char *p;
240
241                 if (info.type != CGROUP_FILE_TYPE_DIR)
242                         goto next;
243
244                 if (asprintf(&p, "%s/%s", path, info.path) < 0) {
245                         ret = -ENOMEM;
246                         break;
247                 }
248
249                 k = cg_kill(controller, p, sig, ignore_self);
250                 free(p);
251
252                 if (k < 0) {
253                         if (ret == 0)
254                                 ret = k;
255                 } else if (k > 0)
256                         killed = true;
257
258         next:
259
260                 r = cgroup_walk_tree_next(0, &iterator, &info, level);
261         }
262
263         if (ret == 0) {
264                 if (r == 0 || r == ECGEOF)
265                         ret = !!killed;
266                 else if (r == ECGOTHER && errno == ENOENT)
267                         ret = -ESRCH;
268                 else
269                         ret = cg_translate_error(r, errno);
270         }
271
272         assert_se(cgroup_walk_tree_end(&iterator) == 0);
273
274         return ret;
275 }
276
277 int cg_kill_recursive_and_wait(const char *controller, const char *path) {
278         unsigned i;
279
280         assert(path);
281         assert(controller);
282
283         /* This safely kills all processes; first it sends a SIGTERM,
284          * then checks 8 times after 50ms whether the group is
285          * now empty, and finally kills everything that is left with
286          * SIGKILL */
287
288         for (i = 0; i < 10; i++) {
289                 int sig, r;
290
291                 if (i <= 0)
292                         sig = SIGTERM;
293                 else if (i >= 9)
294                         sig = SIGKILL;
295                 else
296                         sig = 0;
297
298                 if ((r = cg_kill_recursive(controller, path, sig, true)) <= 0)
299                         return r;
300
301                 usleep(50 * USEC_PER_MSEC);
302         }
303
304         return 0;
305 }
306
307 int cg_migrate(const char *controller, const char *from, const char *to, bool ignore_self) {
308         bool migrated = false, done = false;
309         int r, ret = 0;
310         pid_t my_pid;
311         FILE *f = NULL;
312
313         assert(controller);
314         assert(from);
315         assert(to);
316
317         my_pid = getpid();
318
319         do {
320                 pid_t pid;
321                 done = true;
322
323                 if ((r = cg_enumerate_tasks(controller, from, &f)) < 0)
324                         goto finish;
325
326                 while ((r = cg_read_pid(f, &pid)) > 0) {
327
328                         if (pid == my_pid && ignore_self)
329                                 continue;
330
331                         if ((r = cg_attach(controller, to, pid)) < 0) {
332                                 if (ret == 0)
333                                         ret = -r;
334                         }
335
336                         migrated = true;
337                         done = false;
338                 }
339
340                 fclose(f);
341                 f = NULL;
342
343         } while (!done && r >= 0);
344
345 finish:
346
347         if (f)
348                 fclose(f);
349
350         if (r < 0)
351                 return r;
352
353         if (ret < 0)
354                 return ret;
355
356         return !!migrated;
357 }
358
359 int cg_migrate_recursive(const char *controller, const char *from, const char *to, bool ignore_self) {
360         struct cgroup_file_info info;
361         int level = 0, r, ret = 0;
362         void *iterator = NULL;
363         bool migrated = false;
364
365         assert(controller);
366         assert(from);
367         assert(to);
368
369         zero(info);
370
371         r = cgroup_walk_tree_begin(controller, from, 0, &iterator, &info, &level);
372         while (r == 0) {
373                 int k;
374                 char *p;
375
376                 if (info.type != CGROUP_FILE_TYPE_DIR)
377                         goto next;
378
379                 if (asprintf(&p, "%s/%s", from, info.path) < 0) {
380                         ret = -ENOMEM;
381                         break;
382                 }
383
384                 k = cg_migrate(controller, p, to, ignore_self);
385                 free(p);
386
387                 if (k < 0) {
388                         if (ret == 0)
389                                 ret = k;
390                 } else if (k > 0)
391                         migrated = true;
392
393         next:
394                 r = cgroup_walk_tree_next(0, &iterator, &info, level);
395         }
396
397         if (ret == 0) {
398                 if (r == 0 || r == ECGEOF)
399                         r = !!migrated;
400                 else if (r == ECGOTHER && errno == ENOENT)
401                         r = -ESRCH;
402                 else
403                         r = cg_translate_error(r, errno);
404         }
405
406         assert_se(cgroup_walk_tree_end(&iterator) == 0);
407
408         return ret;
409 }
410
411 int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) {
412         char *mp;
413         int r;
414
415         assert(controller);
416
417         if ((r = cgroup_get_subsys_mount_point(controller, &mp)) != 0)
418                 return cg_translate_error(r, errno);
419
420         if (path && suffix)
421                 r = asprintf(fs, "%s/%s/%s", mp, path, suffix);
422         else if (path)
423                 r = asprintf(fs, "%s/%s", mp, path);
424         else if (suffix)
425                 r = asprintf(fs, "%s/%s", mp, suffix);
426         else {
427                 path_kill_slashes(mp);
428                 *fs = mp;
429                 return 0;
430         }
431
432         free(mp);
433         path_kill_slashes(*fs);
434         return r < 0 ? -ENOMEM : 0;
435 }
436
437 int cg_trim(const char *controller, const char *path, bool delete_root) {
438         char *fs;
439         int r;
440
441         assert(controller);
442         assert(path);
443
444         if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
445                 return r;
446
447         r = rm_rf(fs, true, delete_root);
448         free(fs);
449
450         return r;
451 }
452
453 int cg_delete(const char *controller, const char *path) {
454         struct cgroup *cg;
455         int r;
456
457         assert(controller);
458         assert(path);
459
460         if (!(cg = cg_new(controller, path)))
461                 return -ENOMEM;
462
463         if ((r = cgroup_delete_cgroup_ext(cg, CGFLAG_DELETE_RECURSIVE|CGFLAG_DELETE_IGNORE_MIGRATION)) != 0) {
464                 r = cg_translate_error(r, errno);
465                 goto finish;
466         }
467
468         r = 0;
469
470 finish:
471         cgroup_free(&cg);
472
473         return r;
474 }
475
476 int cg_create(const char *controller, const char *path) {
477         char *fs;
478         int r;
479
480         assert(controller);
481         assert(path);
482
483         if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
484                 return r;
485
486         r = mkdir_p(fs, 0755);
487         free(fs);
488
489         return r;
490 }
491
492 int cg_attach(const char *controller, const char *path, pid_t pid) {
493         char *fs;
494         int r;
495         char c[32];
496
497         assert(controller);
498         assert(path);
499         assert(pid >= 0);
500
501         if ((r = cg_get_path(controller, path, "tasks", &fs)) < 0)
502                 return r;
503
504         if (pid == 0)
505                 pid = getpid();
506
507         snprintf(c, sizeof(c), "%lu\n", (unsigned long) pid);
508         char_array_0(c);
509
510         r = write_one_line_file(fs, c);
511         free(fs);
512
513         return r;
514 }
515
516 int cg_create_and_attach(const char *controller, const char *path, pid_t pid) {
517         int r;
518
519         assert(controller);
520         assert(path);
521         assert(pid >= 0);
522
523         if ((r = cg_create(controller, path)) < 0)
524                 return r;
525
526         if ((r = cg_attach(controller, path, pid)) < 0)
527                 return r;
528
529         /* This does not remove the cgroup on failure */
530
531         return r;
532 }
533
534 int cg_set_group_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid) {
535         char *fs;
536         int r;
537
538         assert(controller);
539         assert(path);
540
541         if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
542                 return r;
543
544         r = chmod_and_chown(fs, mode, uid, gid);
545         free(fs);
546
547         return r;
548 }
549
550 int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid) {
551         char *fs;
552         int r;
553
554         assert(controller);
555         assert(path);
556
557         if ((r = cg_get_path(controller, path, "tasks", &fs)) < 0)
558                 return r;
559
560         r = chmod_and_chown(fs, mode, uid, gid);
561         free(fs);
562
563         return r;
564 }
565
566 int cg_get_by_pid(const char *controller, pid_t pid, char **path) {
567         int r;
568         char *p = NULL;
569         FILE *f;
570         char *fs;
571         size_t cs;
572
573         assert(controller);
574         assert(path);
575         assert(pid >= 0);
576
577         if (pid == 0)
578                 pid = getpid();
579
580         if (asprintf(&fs, "/proc/%lu/cgroup", (unsigned long) pid) < 0)
581                 return -ENOMEM;
582
583         f = fopen(fs, "re");
584         free(fs);
585
586         cs = strlen(controller);
587
588         while (!feof(f)) {
589                 char line[LINE_MAX];
590                 char *l;
591
592                 errno = 0;
593                 if (!(fgets(line, sizeof(line), f))) {
594                         if (feof(f))
595                                 break;
596
597                         r = errno ? -errno : -EIO;
598                         goto finish;
599                 }
600
601                 truncate_nl(line);
602
603                 if (!(l = strchr(line, ':')))
604                         continue;
605
606                 l++;
607                 if (strncmp(l, controller, cs) != 0)
608                         continue;
609
610                 if (l[cs] != ':')
611                         continue;
612
613                 if (!(p = strdup(l + cs + 1))) {
614                         r = -ENOMEM;
615                         goto finish;
616                 }
617
618                 *path = p;
619                 r = 0;
620                 goto finish;
621         }
622
623         r = -ENOENT;
624
625 finish:
626         fclose(f);
627
628         return r;
629 }
630
631 int cg_install_release_agent(const char *controller, const char *agent) {
632         char *fs = NULL, *contents = NULL, *line = NULL, *sc;
633         int r;
634
635         assert(controller);
636         assert(agent);
637
638         if ((r = cg_get_path(controller, NULL, "release_agent", &fs)) < 0)
639                 return r;
640
641         if ((r = read_one_line_file(fs, &contents)) < 0)
642                 goto finish;
643
644         sc = strstrip(contents);
645         if (sc[0] == 0) {
646
647                 if (asprintf(&line, "%s\n", agent) < 0) {
648                         r = -ENOMEM;
649                         goto finish;
650                 }
651
652                 if ((r = write_one_line_file(fs, line)) < 0)
653                         goto finish;
654
655         } else if (!streq(sc, agent)) {
656                 r = -EEXIST;
657                 goto finish;
658         }
659
660         free(fs);
661         fs = NULL;
662         if ((r = cg_get_path(controller, NULL, "notify_on_release", &fs)) < 0) {
663                 r = -ENOMEM;
664                 goto finish;
665         }
666
667         free(contents);
668         contents = NULL;
669         if ((r = read_one_line_file(fs, &contents)) < 0)
670                 goto finish;
671
672         sc = strstrip(contents);
673
674         if (streq(sc, "0")) {
675                 if ((r = write_one_line_file(fs, "1\n")) < 0)
676                         goto finish;
677
678                 r = 1;
679         } else if (!streq(sc, "1")) {
680                 r = -EIO;
681                 goto finish;
682         } else
683                 r = 0;
684
685 finish:
686         free(fs);
687         free(contents);
688         free(line);
689
690         return r;
691 }
692
693 int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
694         pid_t pid;
695         int r;
696         FILE *f;
697         bool found = false;
698
699         assert(controller);
700         assert(path);
701
702         if ((r = cg_enumerate_tasks(controller, path, &f)) < 0)
703                 return r;
704
705         while ((r = cg_read_pid(f, &pid)) > 0) {
706
707                 if (ignore_self && pid == getpid())
708                         continue;
709
710                 found = true;
711                 break;
712         }
713
714         fclose(f);
715
716         if (r < 0)
717                 return r;
718
719         return !found;
720 }
721
722 int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) {
723         struct cgroup_file_info info;
724         int level = 0, r, ret = 0;
725         void *iterator = NULL;
726         bool empty = true;
727
728         assert(controller);
729         assert(path);
730
731         zero(info);
732
733         r = cgroup_walk_tree_begin(controller, path, 0, &iterator, &info, &level);
734         while (r == 0) {
735                 int k;
736                 char *p;
737
738                 if (info.type != CGROUP_FILE_TYPE_DIR)
739                         goto next;
740
741                 if (asprintf(&p, "%s/%s", path, info.path) < 0) {
742                         ret = -ENOMEM;
743                         break;
744                 }
745
746                 k = cg_is_empty(controller, p, ignore_self);
747                 free(p);
748
749                 if (k < 0) {
750                         ret = k;
751                         break;
752                 } else if (k == 0) {
753                         empty = false;
754                         break;
755                 }
756
757         next:
758                 r = cgroup_walk_tree_next(0, &iterator, &info, level);
759         }
760
761         if (ret == 0) {
762                 if (r == 0 || r == ECGEOF)
763                         ret = !!empty;
764                 else if (r == ECGOTHER && errno == ENOENT)
765                         ret = -ESRCH;
766                 else
767                         ret = cg_translate_error(r, errno);
768         }
769
770         assert_se(cgroup_walk_tree_end(&iterator) == 0);
771
772         return ret;
773 }
774
775 int cg_init(void) {
776         int r;
777
778         if ((r = cgroup_init()) != 0)
779                 return cg_translate_error(r, errno);
780
781         return 0;
782 }