1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include <zencore/thread.h>
#include <zencore/zencore.h>
#include <filesystem>
namespace zen {
/** Basic process abstraction
*/
class ProcessHandle
{
public:
ProcessHandle();
ProcessHandle(const ProcessHandle&) = delete;
ProcessHandle& operator=(const ProcessHandle&) = delete;
~ProcessHandle();
void Initialize(int Pid);
void Initialize(int Pid, std::error_code& OutEc);
void Initialize(void* ProcessHandle); /// Initialize with an existing handle - takes ownership of the handle
[[nodiscard]] bool IsRunning() const;
[[nodiscard]] bool IsValid() const;
bool Wait(int TimeoutMs = -1);
bool Wait(int TimeoutMs, std::error_code& OutEc);
int WaitExitCode();
int GetExitCode();
bool Kill();
bool Terminate(int ExitCode);
void Reset();
[[nodiscard]] inline int Pid() const { return m_Pid; }
[[nodiscard]] inline void* Handle() const { return m_ProcessHandle; }
private:
void* m_ProcessHandle = nullptr;
int m_Pid = 0;
#if ZEN_PLATFORM_LINUX || ZEN_PLATFORM_MAC
int m_ExitCode = -1;
#endif
};
/** Basic process creation
*/
struct CreateProcOptions
{
enum
{
Flag_NewConsole = 1 << 0,
Flag_Elevated = 1 << 1,
Flag_Unelevated = 1 << 2,
Flag_NoConsole = 1 << 3,
// This flag creates the new process in a new process group. This is relevant only on Windows, and
// allows sending ctrl-break events to the new process group without also sending it to the current
// process.
Flag_Windows_NewProcessGroup = 1 << 4,
};
const std::filesystem::path* WorkingDirectory = nullptr;
uint32_t Flags = 0;
std::filesystem::path StdoutFile;
};
#if ZEN_PLATFORM_WINDOWS
using CreateProcResult = void*; // handle to the process
#else
using CreateProcResult = int32_t; // pid
#endif
CreateProcResult CreateProc(const std::filesystem::path& Executable,
std::string_view CommandLine, // should also include arg[0] (executable name)
const CreateProcOptions& Options = {});
/** Process monitor - monitors a list of running processes via polling
Intended to be used to monitor a set of "sponsor" processes, where
we need to determine when none of them remain alive
*/
class ProcessMonitor
{
public:
ProcessMonitor();
~ProcessMonitor();
bool IsRunning();
void AddPid(int Pid);
bool IsActive() const;
private:
using HandleType = void*;
mutable RwLock m_Lock;
std::vector<HandleType> m_ProcessHandles;
};
bool IsProcessRunning(int pid);
bool IsProcessRunning(int pid, std::error_code& OutEc);
int GetCurrentProcessId();
int GetProcessId(CreateProcResult ProcId);
std::filesystem::path GetProcessExecutablePath(int Pid, std::error_code& OutEc);
std::error_code FindProcess(const std::filesystem::path& ExecutableImage, ProcessHandle& OutHandle, bool IncludeSelf = true);
/** Wait for all threads in the current process to exit (except the calling thread)
*
* This is only implemented on Windows currently. The use-case for this is to try
* and ensure that all threads have exited before exiting main() in order to
* avoid some issues which can occur if threads are still running during process
* shutdown especially when the CRT is statically linked into the executable.
*
* This is a best-effort function and may return before all threads have exited.
*/
void WaitForThreads(uint64_t WaitTimeMs);
#if ZEN_PLATFORM_LINUX
void IgnoreChildSignals();
#endif
struct ProcessMetrics
{
uint64_t MemoryBytes = 0;
uint64_t KernelTimeMs = 0;
uint64_t UserTimeMs = 0;
uint64_t WorkingSetSize = 0;
uint64_t PeakWorkingSetSize = 0;
uint64_t PagefileUsage = 0;
uint64_t PeakPagefileUsage = 0;
};
void GetProcessMetrics(ProcessHandle& Handle, ProcessMetrics& OutMetrics);
void process_forcelink(); // internal
} // namespace zen
|