aboutsummaryrefslogtreecommitdiff
path: root/src/zencore/include/zencore/process.h
blob: 42b997c39be225c7fff296c5c540de648048c9e7 (plain) (blame)
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
// 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:
	ZENCORE_API ProcessHandle();

	ProcessHandle(const ProcessHandle&) = delete;
	ProcessHandle& operator=(const ProcessHandle&) = delete;

	ZENCORE_API ~ProcessHandle();

	ZENCORE_API void			   Initialize(int Pid);
	ZENCORE_API void			   Initialize(int Pid, std::error_code& OutEc);
	ZENCORE_API void			   Initialize(void* ProcessHandle);	 /// Initialize with an existing handle - takes ownership of the handle
	ZENCORE_API [[nodiscard]] bool IsRunning() const;
	ZENCORE_API [[nodiscard]] bool IsValid() const;
	ZENCORE_API bool			   Wait(int TimeoutMs = -1);
	ZENCORE_API bool			   Wait(int TimeoutMs, std::error_code& OutEc);
	ZENCORE_API int				   WaitExitCode();
	ZENCORE_API int				   GetExitCode();
	ZENCORE_API bool			   Terminate(int ExitCode);
	ZENCORE_API void			   Reset();
	[[nodiscard]] inline int	   Pid() const { return m_Pid; }

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,
	};

	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

ZENCORE_API 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();

	ZENCORE_API bool IsRunning();
	ZENCORE_API void AddPid(int Pid);
	ZENCORE_API bool IsActive() const;

private:
	using HandleType = void*;

	mutable RwLock			m_Lock;
	std::vector<HandleType> m_ProcessHandles;
};

ZENCORE_API bool IsProcessRunning(int pid);
ZENCORE_API bool IsProcessRunning(int pid, std::error_code& OutEc);
ZENCORE_API 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);

void process_forcelink();  // internal

}  // namespace zen