[CRIU] [PATCH 1/2] --freeze-cgroup: should also seize tasks in sub-cgroups
Andrew Vagin
avagin at virtuozzo.com
Fri Nov 20 05:46:15 PST 2015
On Thu, Nov 19, 2015 at 09:15:59AM -0700, Tycho Andersen wrote:
> Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
> CC: Andrew Vagin <avagin at virtuozzo.com>
> ---
> seize.c | 124 +++++++++++++++++++++++++++++++++++++++++++---------------------
> 1 file changed, 84 insertions(+), 40 deletions(-)
>
> diff --git a/seize.c b/seize.c
> index 943f9d1..3281dd0 100644
> --- a/seize.c
> +++ b/seize.c
> @@ -79,12 +79,93 @@ static int freezer_restore_state(void)
> return 0;
> }
>
> +static int seize_cgroup_tree(char *root_path, const char *state)
> +{
> + DIR *dir;
> + struct dirent *de;
> + char path[PATH_MAX];
> + FILE *f;
> +
> + /*
> + * New tasks can appear while a freezer state isn't
> + * frozen, so we need to catch all new tasks.
> + */
> + snprintf(path, sizeof(path), "%s/tasks", root_path);
> + f = fopen(path, "r");
> + if (f == NULL) {
> + pr_perror("Unable to open %s", path);
> + return -1;
> + }
> + while (fgets(path, sizeof(path), f)) {
> + pid_t pid;
> + int ret;
> +
> + pid = atoi(path);
> +
> + /*
> + * Here we are going to skip tasks which are already traced.
> + * Ptraced tasks looks like children for us, so if
> + * a task isn't ptraced yet, waitpid() will return a error.
> + */
> + ret = wait4(pid, NULL, __WALL | WNOHANG, NULL);
> + if (ret == 0)
> + continue;
> +
> + if (seize_catch_task(pid) && state == frozen) {
> + char buf[] = "/proc/XXXXXXXXXX/exe";
> + struct stat st;
> +
> + /* skip kernel threads */
> + snprintf(buf, sizeof(buf), "/proc/%d/exe", pid);
> + if (stat(buf, &st) == -1 && errno == ENOENT)
> + continue;
> +
> + /* fails when meets a zombie */
> + pr_err("zombie found while seizing\n");
> + fclose(f);
> + return -1;
> + }
> + }
> + fclose(f);
> +
> + dir = opendir(root_path);
> + if (!dir) {
> + pr_perror("Unable to open %s", root_path);
> + return -1;
> + }
> +
> + while ((de = readdir(dir))) {
> + struct stat st;
> +
> + if (dir_dots(de))
> + continue;
> +
> + sprintf(path, "%s/%s", root_path, de->d_name);
> +
> + if (fstatat(dirfd(dir), de->d_name, &st, 0) < 0) {
> + pr_perror("stat of %s failed", path);
> + closedir(dir);
> + return -1;
> + }
> +
> + if (!S_ISDIR(st.st_mode))
> + continue;
> +
> + if (seize_cgroup_tree(path, state) < 0) {
I don't like this recursion. We don't know how deep it is, so are you
sure that we will not have a problem with too big stack?
> + closedir(dir);
> + return -1;
> + }
> + }
> + closedir(dir);
> +
> + return 0;
> +}
> +
> static int freeze_processes(void)
> {
> - int i, ret, fd, exit_code = -1;
> + int i, fd, exit_code = -1;
> char path[PATH_MAX];
> const char *state = thawed;
> - FILE *f;
>
> snprintf(path, sizeof(path), "%s/freezer.state", opts.freeze_cgroup);
> fd = open(path, O_RDWR);
> @@ -117,45 +198,8 @@ static int freeze_processes(void)
> struct timespec req = {};
> u64 timeout;
>
> - /*
> - * New tasks can appear while a freezer state isn't
> - * frozen, so we need to catch all new tasks.
> - */
> - snprintf(path, sizeof(path), "%s/tasks", opts.freeze_cgroup);
> - f = fopen(path, "r");
> - if (f == NULL) {
> - pr_perror("Unable to open %s", path);
> + if (seize_cgroup_tree(opts.freeze_cgroup, state) < 0)
> goto err;
> - }
> - while (fgets(path, sizeof(path), f)) {
> - pid_t pid;
> -
> - pid = atoi(path);
> -
> - /*
> - * Here we are going to skip tasks which are already traced.
> - * Ptraced tasks looks like children for us, so if
> - * a task isn't ptraced yet, waitpid() will return a error.
> - */
> - ret = wait4(pid, NULL, __WALL | WNOHANG, NULL);
> - if (ret == 0)
> - continue;
> -
> - if (seize_catch_task(pid) && state == frozen) {
> - char buf[] = "/proc/XXXXXXXXXX/exe";
> - struct stat st;
> -
> - /* skip kernel threads */
> - snprintf(buf, sizeof(buf), "/proc/%d/exe", pid);
> - if (stat(buf, &st) == -1 && errno == ENOENT)
> - continue;
> -
> - /* fails when meets a zombie */
> - fclose(f);
> - goto err;
> - }
> - }
> - fclose(f);
>
> if (state == frozen)
> break;
> --
> 2.6.2
>
More information about the CRIU
mailing list