diff --git a/files.c b/files.c index 8c01f680c..cb34c4886 100644 --- a/files.c +++ b/files.c @@ -498,18 +498,33 @@ static int open_fdinfos(int pid, struct list_head *list, int state) static int close_old_fds(struct pstree_item *me) { - /* - * FIXME -- The existing test_init implementation uses system() - * which in turn doesn't work when all fds are closed - */ - if (me->pid.virt == 1) - return 0; + DIR *dir; + struct dirent *de; + int fd, ret; + + dir = opendir_proc(getpid(), "fd"); + if (dir == NULL) + return -1; + + while ((de = readdir(dir))) { + if (!strcmp(de->d_name, ".")) + continue; + if (!strcmp(de->d_name, "..")) + continue; + + ret = sscanf(de->d_name, "%d", &fd); + if (ret != 1) { + pr_err("Can't parse %s\n", de->d_name); + return -1; + } + + if ((!is_any_service_fd(fd)) && (dirfd(dir) != fd)) + close_safe(&fd); + } + + closedir(dir); + close_pid_proc(); - /* FIXME -- wait for nextfd syscall (or read proc) */ - close(0); - close(1); - close(2); - close(255); /* bash */ return 0; } diff --git a/include/crtools.h b/include/crtools.h index dd678545c..3c31b8829 100644 --- a/include/crtools.h +++ b/include/crtools.h @@ -123,6 +123,7 @@ enum sfd_type { extern int init_service_fd(void); extern int get_service_fd(enum sfd_type type); extern bool is_service_fd(int fd, enum sfd_type type); +extern bool is_any_service_fd(int fd); /* file descriptors template */ struct cr_fd_desc_tmpl { diff --git a/util.c b/util.c index 72d078d98..f1f015508 100644 --- a/util.c +++ b/util.c @@ -281,10 +281,21 @@ int init_service_fd(void) return 0; } +static int __get_service_fd(enum sfd_type type) +{ + return service_fd_rlim_cur - type; +} + int get_service_fd(enum sfd_type type) { BUG_ON((int)type <= SERVICE_FD_MIN || (int)type >= SERVICE_FD_MAX); - return service_fd_rlim_cur - type; + return __get_service_fd(type); +} + +bool is_any_service_fd(int fd) +{ + return fd > __get_service_fd(SERVICE_FD_MAX) && + fd < __get_service_fd(SERVICE_FD_MIN); } bool is_service_fd(int fd, enum sfd_type type)