Core/Process: Improve Posix implementation

- Handle chdir errors
- Calls _exit if execve failed
- Better format the code
This commit is contained in:
SirLynix 2024-01-23 09:37:01 +01:00 committed by Jérôme Leclercq
parent ac1422c221
commit 8ee128b475
1 changed files with 48 additions and 27 deletions

View File

@ -38,6 +38,20 @@ namespace Nz::PlatformImpl
// Child process // Child process
::setsid(); ::setsid();
if (!workingDirectory.empty())
{
if (::chdir(workingDirectory.c_str()) != 0)
{
PidOrErr err;
err.pid = grandChildPid;
pipe.Write(&err, sizeof(err));
// Early exit
std::exit(1);
}
}
pid_t grandChildPid = ::vfork(); pid_t grandChildPid = ::vfork();
if (grandChildPid == 0) if (grandChildPid == 0)
{ {
@ -53,17 +67,18 @@ namespace Nz::PlatformImpl
char* envs[] = { nullptr }; char* envs[] = { nullptr };
if (!workingDirectory.empty()) ::execve(program.c_str(), argv.data(), envs);
::chdir(workingDirectory.c_str());
if (::execve(program.c_str(), argv.data(), envs) == -1) // 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
PidOrErr err;
err.pid = -1;
err.err = errno;
pipe.Write(&err, sizeof(err)); PidOrErr err;
} err.pid = -1;
err.err = errno;
pipe.Write(&err, sizeof(err));
_exit(1);
} }
else if (grandChildPid != -1) else if (grandChildPid != -1)
{ {
@ -71,6 +86,9 @@ namespace Nz::PlatformImpl
err.pid = grandChildPid; err.pid = grandChildPid;
pipe.Write(&err, sizeof(err)); pipe.Write(&err, sizeof(err));
// Exits the child process, at this point the grand-child should have started
std::exit(0);
} }
else else
{ {
@ -79,28 +97,31 @@ namespace Nz::PlatformImpl
err.err = errno; err.err = errno;
pipe.Write(&err, sizeof(err)); pipe.Write(&err, sizeof(err));
std::exit(1);
} }
// Exits the child process, at this point the grand-child should have started __builtin_unreachable(); // TODO: NAZARA_UNREACHABLE()
std::exit(0);
} }
else
// Parent process
// Wait for and reap the child
int childStatus;
::waitpid(childPid, &childStatus, 0);
PidOrErr pidOrErr;
if (pipe.Read(&pidOrErr, sizeof(pidOrErr) != sizeof(pidOrErr)))
{ {
// this should never happen // Parent process
return Err("failed to create child: couldn't retrieve status from pipe");
// Wait for and reap the child
int childStatus;
::waitpid(childPid, &childStatus, 0);
PidOrErr pidOrErr;
if (pipe.Read(&pidOrErr, sizeof(pidOrErr) != sizeof(pidOrErr)))
{
// this should never happen
return Err("failed to create child: couldn't retrieve status from pipe");
}
if (pidOrErr.pid < 0)
return Err(Error::GetLastSystemError(pidOrErr.err));
return SafeCast<Pid>(pidOrErr.pid);
} }
if (pidOrErr.pid < 0)
return Err(Error::GetLastSystemError(pidOrErr.err));
return SafeCast<Pid>(pidOrErr.pid);
} }
} }