| // Copyright 2026 Google Inc. All Rights Reserved. |
| // |
| // 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. |
| |
| #ifndef NINJA_PROCESS_TREE_H |
| #define NINJA_PROCESS_TREE_H |
| |
| #include <string> |
| #include <unordered_map> |
| #include <vector> |
| |
| #ifdef _WIN32 |
| #include <windows.h> |
| #else |
| #include <sys/types.h> |
| #endif |
| |
| /// Detailed information about a process, gathered after the initial snapshot. |
| struct ProcessDetails { |
| /// Full command line arguments. |
| std::vector<std::string> command_line; |
| |
| /// Whether the details were successfully collected. |
| bool collected = false; |
| }; |
| |
| /// A class used to represent the tree of processes running on the system. |
| /// This can be used to display which child processes are still running |
| /// when Ninja is interrupted. |
| class ProcessTree { |
| public: |
| #ifdef _WIN32 |
| using Pid = DWORD; |
| #else |
| using Pid = pid_t; |
| #endif |
| |
| struct ProcessInfo { |
| /// The unique process identifier. |
| Pid pid; |
| |
| /// The process identifier of the parent process. |
| Pid ppid; |
| |
| /// Short executable name (e.g. "cc1plus"). |
| std::string name; |
| |
| /// Detailed information about the process, such as the full command line. |
| ProcessDetails details; |
| }; |
| |
| /// A snapshot of all processes running on the system, indexed for |
| /// efficient tree construction. |
| struct SystemSnapshot { |
| std::vector<ProcessInfo> processes; |
| std::unordered_map<Pid, std::vector<Pid>> ppid_to_children; |
| std::unordered_map<Pid, const ProcessInfo*> pid_to_info; |
| }; |
| |
| /// Default constructor creates an empty tree. |
| ProcessTree() = default; |
| |
| /// Build a tree containing only the descendants of |root_pid| from a |
| /// pre-built system snapshot. |
| ProcessTree(Pid root_pid, const SystemSnapshot& snapshot); |
| |
| /// Capture a list of all processes currently running on the system, |
| /// and build the indexes for fast tree construction. |
| static SystemSnapshot TakeSystemSnapshot(); |
| |
| /// Recursively gather more detailed information for all processes in this |
| /// tree. |
| void CollectDetails(); |
| |
| /// Append the process tree representation to |out|, starting from |
| /// the root PID it was initialized with. |
| /// |known_descriptions| can override the description for specific PIDs. |
| void Print(int indent, |
| const std::unordered_map<Pid, std::string>& known_descriptions, |
| std::string* out) const; |
| |
| private: |
| /// Capture a list of all processes currently running on the system. |
| /// This is a flat list and does not build the tree yet. |
| static std::vector<ProcessInfo> GetSystemProcesses(); |
| |
| /// Platform-specific helper to get details for a single process. |
| static void GetSystemProcessDetails(Pid pid, ProcessDetails* details); |
| |
| /// Recursively collect descendants and build the tree. |
| void BuildFrom( |
| Pid parent_pid, |
| const std::unordered_map<Pid, std::vector<Pid>>& ppid_to_children, |
| const std::unordered_map<Pid, const ProcessInfo*>& pid_to_info); |
| |
| Pid root_pid_ = 0; |
| |
| /// Map from parent PID to the list of its immediate children's PIDs, |
| /// containing only processes in this tree. |
| using PidMap = std::unordered_map<Pid, std::vector<Pid>>; |
| PidMap ppid_to_children_; |
| |
| /// Map from PID to the process information for processes in this tree. |
| std::unordered_map<Pid, ProcessInfo> all_processes_; |
| }; |
| |
| #endif // NINJA_PROCESS_TREE_H |