blob: c4408ebcb605b5664f0af9cf0be7af793eb47089 [file] [edit]
// 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