diff options
Diffstat (limited to 'cmds/installd/utils.cpp')
-rw-r--r-- | cmds/installd/utils.cpp | 78 |
1 files changed, 59 insertions, 19 deletions
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp index faccded34b..f04ee337d9 100644 --- a/cmds/installd/utils.cpp +++ b/cmds/installd/utils.cpp @@ -19,18 +19,21 @@ #include <errno.h> #include <fcntl.h> #include <fts.h> +#include <poll.h> #include <stdlib.h> #include <sys/capability.h> +#include <sys/pidfd.h> #include <sys/stat.h> #include <sys/statvfs.h> #include <sys/wait.h> #include <sys/xattr.h> +#include <unistd.h> #include <uuid/uuid.h> #include <android-base/file.h> #include <android-base/logging.h> -#include <android-base/strings.h> #include <android-base/stringprintf.h> +#include <android-base/strings.h> #include <android-base/unique_fd.h> #include <cutils/fs.h> #include <cutils/properties.h> @@ -1059,30 +1062,45 @@ int ensure_config_user_dirs(userid_t userid) { return fs_prepare_dir(path.c_str(), 0750, uid, gid); } -int wait_child(pid_t pid) -{ +static int wait_child(pid_t pid) { int status; - pid_t got_pid; + pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, /*options=*/0)); - while (1) { - got_pid = waitpid(pid, &status, 0); - if (got_pid == -1 && errno == EINTR) { - printf("waitpid interrupted, retrying\n"); - } else { - break; - } - } if (got_pid != pid) { - ALOGW("waitpid failed: wanted %d, got %d: %s\n", - (int) pid, (int) got_pid, strerror(errno)); - return 1; + PLOG(ERROR) << "waitpid failed: wanted " << pid << ", got " << got_pid; + return W_EXITCODE(/*exit_code=*/255, /*signal_number=*/0); } - if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { - return 0; - } else { - return status; /* always nonzero */ + return status; +} + +int wait_child_with_timeout(pid_t pid, int timeout_ms) { + int pidfd = pidfd_open(pid, /*flags=*/0); + if (pidfd < 0) { + PLOG(ERROR) << "pidfd_open failed for pid " << pid; + kill(pid, SIGKILL); + return wait_child(pid); + } + + struct pollfd pfd; + pfd.fd = pidfd; + pfd.events = POLLIN; + int poll_ret = TEMP_FAILURE_RETRY(poll(&pfd, /*nfds=*/1, timeout_ms)); + + close(pidfd); + + if (poll_ret < 0) { + PLOG(ERROR) << "poll failed for pid " << pid; + kill(pid, SIGKILL); + return wait_child(pid); } + if (poll_ret == 0) { + LOG(WARNING) << "Child process " << pid << " timed out after " << timeout_ms + << "ms. Killing it"; + kill(pid, SIGKILL); + return wait_child(pid); + } + return wait_child(pid); } /** @@ -1295,5 +1313,27 @@ void drop_capabilities(uid_t uid) { } } +bool remove_file_at_fd(int fd, /*out*/ std::string* path) { + char path_buffer[PATH_MAX + 1]; + std::string proc_path = android::base::StringPrintf("/proc/self/fd/%d", fd); + ssize_t len = readlink(proc_path.c_str(), path_buffer, PATH_MAX); + if (len < 0) { + PLOG(WARNING) << "Could not remove file at fd " << fd << ": Failed to get file path"; + return false; + } + path_buffer[len] = '\0'; + if (path != nullptr) { + *path = path_buffer; + } + if (unlink(path_buffer) != 0) { + if (errno == ENOENT) { + return true; + } + PLOG(WARNING) << "Could not remove file at path " << path_buffer; + return false; + } + return true; +} + } // namespace installd } // namespace android |