/* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "perfetto/ext/base/subprocess.h" #include "perfetto/base/build_config.h" #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) #include <fcntl.h> #include <poll.h> #include <signal.h> #include <stdio.h> #include <sys/resource.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <algorithm> #include <thread> #include <tuple> #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) #include <sys/prctl.h> #endif #include "perfetto/base/logging.h" #include "perfetto/base/time.h" #include "perfetto/ext/base/utils.h" // In MacOS this is not defined in any header. extern "C" char** environ; namespace perfetto { namespace base { namespace { struct ChildProcessArgs { … }; // Don't add any dynamic allocation in this function. This will be invoked // under a fork(), potentially in a state where the allocator lock is held. void __attribute__((noreturn)) ChildProcess(ChildProcessArgs* args) { … } } // namespace // static const int Subprocess::kTimeoutSignal = …; void Subprocess::Start() { … } Subprocess::Status Subprocess::Poll() { … } // |timeout_ms| semantic: // -1: Block indefinitely. // 0: Don't block, return immediately. // >0: Block for at most X ms. // Returns: // True: Read at least one fd (so there might be more queued). // False: if all fds reached quiescent (no data to read/write). bool Subprocess::PollInternal(int poll_timeout_ms) { … } bool Subprocess::Wait(int timeout_ms) { … } void Subprocess::TryReadExitStatus() { … } // If the stidn pipe is still open, push input data and close it at the end. void Subprocess::TryPushStdin() { … } void Subprocess::TryReadStdoutAndErr() { … } void Subprocess::KillAndWaitForTermination(int sig_num) { … } } // namespace base } // namespace perfetto #endif // PERFETTO_OS_LINUX || PERFETTO_OS_ANDROID || PERFETTO_OS_APPLE