Core/Process: Improve Posix implementation
- Handle chdir errors - Calls _exit if execve failed - Better format the code
This commit is contained in:
parent
ac1422c221
commit
8ee128b475
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue