Core/Process: Add Exists function
This commit is contained in:
parent
b0648918a7
commit
b63c9fcc49
|
|
@ -29,6 +29,7 @@ namespace Nz
|
||||||
Process& operator=(const Process&) = delete;
|
Process& operator=(const Process&) = delete;
|
||||||
Process& operator=(Process&&) = delete;
|
Process& operator=(Process&&) = delete;
|
||||||
|
|
||||||
|
static Result<bool, std::string> Exists(Pid pid);
|
||||||
static Pid GetCurrentPid();
|
static Pid GetCurrentPid();
|
||||||
static Result<Pid, std::string> SpawnDetached(const std::filesystem::path& program, std::span<const std::string> arguments = {}, const std::filesystem::path& workingDirectory = {});
|
static Result<Pid, std::string> SpawnDetached(const std::filesystem::path& program, std::span<const std::string> arguments = {}, const std::filesystem::path& workingDirectory = {});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,17 @@
|
||||||
|
|
||||||
namespace Nz::PlatformImpl
|
namespace Nz::PlatformImpl
|
||||||
{
|
{
|
||||||
|
Result<bool, std::string> CheckProcessExistence(Pid pid)
|
||||||
|
{
|
||||||
|
if (::kill(pid, 0) == 0)
|
||||||
|
return Ok(true);
|
||||||
|
|
||||||
|
if (errno == ESRCH)
|
||||||
|
return OK(false);
|
||||||
|
|
||||||
|
return Err(Error::GetLastSystemError());
|
||||||
|
}
|
||||||
|
|
||||||
Pid GetCurrentProcessId()
|
Pid GetCurrentProcessId()
|
||||||
{
|
{
|
||||||
return ::getpid();
|
return ::getpid();
|
||||||
|
|
@ -34,6 +45,8 @@ namespace Nz::PlatformImpl
|
||||||
|
|
||||||
// Double fork (see https://0xjet.github.io/3OHA/2022/04/11/post.html)
|
// Double fork (see https://0xjet.github.io/3OHA/2022/04/11/post.html)
|
||||||
// We will create a child and a grand-child process, using a pipe to retrieve the grand-child pid
|
// We will create a child and a grand-child process, using a pipe to retrieve the grand-child pid
|
||||||
|
// TODO: Maybe use vfork for the child process too?
|
||||||
|
// TODO: Use posix_spawn if possible instead
|
||||||
pid_t childPid = ::fork();
|
pid_t childPid = ::fork();
|
||||||
if (childPid == -1)
|
if (childPid == -1)
|
||||||
return Err("failed to create child: " + Error::GetLastSystemError());
|
return Err("failed to create child: " + Error::GetLastSystemError());
|
||||||
|
|
@ -76,7 +89,7 @@ namespace Nz::PlatformImpl
|
||||||
::execve(program.c_str(), argv.data(), envs);
|
::execve(program.c_str(), argv.data(), envs);
|
||||||
|
|
||||||
// If we get here, execve failed
|
// If we get here, execve failed
|
||||||
// Remember we share the memory of our parent (vfork) so we need to exit using _exit() to avoid calling the parent exit handler
|
// Remember we share the memory of our parent (vfork) so we need to exit using _exit() to avoid calling the parent exit handlers
|
||||||
|
|
||||||
PidOrErr err;
|
PidOrErr err;
|
||||||
err.pid = -1;
|
err.pid = -1;
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
namespace Nz::PlatformImpl
|
namespace Nz::PlatformImpl
|
||||||
{
|
{
|
||||||
|
Result<bool, std::string> CheckProcessExistence(Pid pid);
|
||||||
Pid GetCurrentProcessId();
|
Pid GetCurrentProcessId();
|
||||||
Result<Pid, std::string> SpawnDetachedProcess(const std::filesystem::path& program, std::span<const std::string> arguments = {}, const std::filesystem::path& workingDirectory = {});
|
Result<Pid, std::string> SpawnDetachedProcess(const std::filesystem::path& program, std::span<const std::string> arguments = {}, const std::filesystem::path& workingDirectory = {});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,11 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
Result<bool, std::string> Process::Exists(Pid pid)
|
||||||
|
{
|
||||||
|
return PlatformImpl::CheckProcessExistence(pid);
|
||||||
|
}
|
||||||
|
|
||||||
Pid Process::GetCurrentPid()
|
Pid Process::GetCurrentPid()
|
||||||
{
|
{
|
||||||
return PlatformImpl::GetCurrentProcessId();
|
return PlatformImpl::GetCurrentProcessId();
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include <Nazara/Core/Error.hpp>
|
#include <Nazara/Core/Error.hpp>
|
||||||
#include <Nazara/Core/StringExt.hpp>
|
#include <Nazara/Core/StringExt.hpp>
|
||||||
#include <Nazara/Core/Win32/Win32Utils.hpp>
|
#include <Nazara/Core/Win32/Win32Utils.hpp>
|
||||||
|
#include <NazaraUtils/CallOnExit.hpp>
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <Nazara/Core/Debug.hpp>
|
#include <Nazara/Core/Debug.hpp>
|
||||||
|
|
||||||
|
|
@ -85,6 +86,27 @@ namespace Nz::PlatformImpl
|
||||||
return commandLine;
|
return commandLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<bool, std::string> CheckProcessExistence(Pid pid)
|
||||||
|
{
|
||||||
|
HANDLE processHandle = ::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
|
||||||
|
if (!processHandle)
|
||||||
|
{
|
||||||
|
DWORD lastErr = ::GetLastError();
|
||||||
|
if (lastErr == ERROR_INVALID_PARAMETER)
|
||||||
|
return Ok(false);
|
||||||
|
|
||||||
|
return Err("failed to open process handle: " + Error::GetLastSystemError());
|
||||||
|
}
|
||||||
|
CallOnExit releaseHandle([processHandle] { ::CloseHandle(processHandle); });
|
||||||
|
|
||||||
|
// Opening a handle doesn't mean the process hasn't exited (zombie processes), check if it has an exit code
|
||||||
|
DWORD exitCode;
|
||||||
|
if (!::GetExitCodeProcess(processHandle, &exitCode))
|
||||||
|
return Err("failed to get exit code: " + Error::GetLastSystemError());
|
||||||
|
|
||||||
|
return Ok(exitCode == STILL_ACTIVE);
|
||||||
|
}
|
||||||
|
|
||||||
Pid GetCurrentProcessId()
|
Pid GetCurrentProcessId()
|
||||||
{
|
{
|
||||||
return ::GetCurrentProcessId();
|
return ::GetCurrentProcessId();
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
namespace Nz::PlatformImpl
|
namespace Nz::PlatformImpl
|
||||||
{
|
{
|
||||||
|
Result<bool, std::string> CheckProcessExistence(Pid pid);
|
||||||
Pid GetCurrentProcessId();
|
Pid GetCurrentProcessId();
|
||||||
Result<Pid, std::string> SpawnDetachedProcess(const std::filesystem::path& program, std::span<const std::string> arguments = {}, const std::filesystem::path& workingDirectory = {});
|
Result<Pid, std::string> SpawnDetachedProcess(const std::filesystem::path& program, std::span<const std::string> arguments = {}, const std::filesystem::path& workingDirectory = {});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue