[*] Linux: begin catching up AuProcesses to NT
This commit is contained in:
parent
81775a76bf
commit
d166a00d81
@ -29,12 +29,7 @@
|
|||||||
|
|
||||||
namespace Aurora::IO
|
namespace Aurora::IO
|
||||||
{
|
{
|
||||||
AuUInt64 AFileHandle::DupHandle(AuUInt64 uOSHandle, bool bWriteAccess)
|
AuUInt64 DupHandle(AuUInt64 uOSHandle, bool bWriteAccess, bool bShareAccess)
|
||||||
{
|
|
||||||
return DupHandle(uOSHandle, bWriteAccess, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
AuUInt64 AFileHandle::DupHandle(AuUInt64 uOSHandle, bool bWriteAccess, bool bShareAccess)
|
|
||||||
{
|
{
|
||||||
int fd = ::dup(uOSHandle);
|
int fd = ::dup(uOSHandle);
|
||||||
|
|
||||||
@ -42,13 +37,34 @@ namespace Aurora::IO
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int flags = ::fcntl(fd, F_GETFL, 0);
|
if (!SetFDShareAccess(uOSHandle, bShareAccess))
|
||||||
if (flags == -1)
|
|
||||||
{
|
{
|
||||||
::close(fd);
|
::close(fd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return AuUInt64(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
AuUInt64 AFileHandle::DupHandle(AuUInt64 uOSHandle, bool bWriteAccess)
|
||||||
|
{
|
||||||
|
return Aurora::IO::DupHandle(uOSHandle, bWriteAccess, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AuUInt64 AFileHandle::DupHandle(AuUInt64 uOSHandle, bool bWriteAccess, bool bShareAccess)
|
||||||
|
{
|
||||||
|
return Aurora::IO::DupHandle(uOSHandle, bWriteAccess, bShareAccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SetFDShareAccess(AuUInt64 uOSHandle, bool bShareAccess)
|
||||||
|
{
|
||||||
|
int flags = ::fcntl(uOSHandle, F_GETFL, 0);
|
||||||
|
if (flags == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (bShareAccess)
|
if (bShareAccess)
|
||||||
{
|
{
|
||||||
@ -59,14 +75,13 @@ namespace Aurora::IO
|
|||||||
flags |= FD_CLOEXEC;
|
flags |= FD_CLOEXEC;
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = ::fcntl(fd, F_SETFL, flags);
|
flags = ::fcntl(uOSHandle, F_SETFL, flags);
|
||||||
if (flags == -1)
|
if (flags == -1)
|
||||||
{
|
{
|
||||||
::close(fd);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return AuUInt64(fd);
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AFileHandle::CloseHandle(AuUInt64 uOSHandle)
|
void AFileHandle::CloseHandle(AuUInt64 uOSHandle)
|
||||||
|
@ -9,5 +9,6 @@
|
|||||||
|
|
||||||
namespace Aurora::IO
|
namespace Aurora::IO
|
||||||
{
|
{
|
||||||
|
int SetFDShareAccess(AuUInt64 uOSHandle, bool bShareAccess);
|
||||||
|
AuUInt64 DupHandle(AuUInt64 uOSHandle, bool bWriteAccess, bool bShareAccess);
|
||||||
}
|
}
|
@ -17,6 +17,7 @@
|
|||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
#include <Source/Threading/Primitives/AuSemaphore.Unix.hpp>
|
#include <Source/Threading/Primitives/AuSemaphore.Unix.hpp>
|
||||||
|
#include <Source/IO/AuIOHandle.Unix.hpp>
|
||||||
|
|
||||||
#if defined(AURORA_COMPILER_CLANG)
|
#if defined(AURORA_COMPILER_CLANG)
|
||||||
// warning: enumeration values 'kEnumCount' and 'kEnumInvalid' not handled in switch [-Wswitch
|
// warning: enumeration values 'kEnumCount' and 'kEnumInvalid' not handled in switch [-Wswitch
|
||||||
@ -225,7 +226,8 @@ namespace Aurora::Processes
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
tmp = ::read(handle, destination.ptr, destination.length);
|
tmp = ::read(handle, destination.ptr, destination.length);
|
||||||
} while ((tmp == -1 && errno == EINTR));
|
}
|
||||||
|
while ((tmp == -1 && errno == EINTR));
|
||||||
|
|
||||||
if (tmp <= 0)
|
if (tmp <= 0)
|
||||||
{
|
{
|
||||||
@ -267,16 +269,62 @@ namespace Aurora::Processes
|
|||||||
::fcntl(handle, F_SETFL, control);
|
::fcntl(handle, F_SETFL, control);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return ::write(handle, source.ptr, source.length) == source.length;
|
return ::write(handle, source.ptr, source.length) == source.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool InitProcessStdHandles(EStreamForward fwd, int *fds)
|
static bool InitProcessStdHandles(EStreamForward fwd, int *fds, AuIO::EStandardStream stream, IO::IIOHandle *pHandle)
|
||||||
{
|
{
|
||||||
|
AuOptionalEx<AuUInt64> optHandle;
|
||||||
|
bool bIsRead = stream == AuIO::EStandardStream::eInputStream;
|
||||||
|
|
||||||
switch (fwd)
|
switch (fwd)
|
||||||
{
|
{
|
||||||
|
case EStreamForward::eIOHandle:
|
||||||
|
optHandle = pHandle->GetOSHandleSafe();
|
||||||
|
|
||||||
|
if (!optHandle)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bIsRead)
|
||||||
|
{
|
||||||
|
fds[0] = dup((int)optHandle.value());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fds[1] = dup((int)optHandle.value());
|
||||||
|
}
|
||||||
|
break;
|
||||||
case EStreamForward::eCurrentProcess:
|
case EStreamForward::eCurrentProcess:
|
||||||
// Intentionally NO-OP
|
if (stream == AuIO::EStandardStream::eInputStream)
|
||||||
|
{
|
||||||
|
fds[0] = dup(STDIN_FILENO);
|
||||||
|
if (fds[0] < 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (stream == AuIO::EStandardStream::eErrorStream)
|
||||||
|
{
|
||||||
|
fds[1] = dup(STDERR_FILENO);
|
||||||
|
if (fds[1] < 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (stream == AuIO::EStandardStream::eOutputStream)
|
||||||
|
{
|
||||||
|
fds[1] = dup(STDOUT_FILENO);
|
||||||
|
if (fds[1] < 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case EStreamForward::eAsyncPipe:
|
case EStreamForward::eAsyncPipe:
|
||||||
if (::pipe(fds))
|
if (::pipe(fds))
|
||||||
@ -286,22 +334,52 @@ namespace Aurora::Processes
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EStreamForward::eNull:
|
case EStreamForward::eNull:
|
||||||
fds[0] = ::open("/dev/null", O_RDWR);
|
if (bIsRead)
|
||||||
fds[1] = ::open("/dev/null", O_RDWR);
|
{
|
||||||
|
fds[0] = ::open("/dev/null", O_RDWR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fds[1] = ::open("/dev/null", O_RDWR);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case EStreamForward::eNewConsoleWindow:
|
case EStreamForward::eNewConsoleWindow:
|
||||||
SysPushErrorGeneric("AuProcesses is not the right place for PTY support. At least not in this form (this level of abstraction only cares for pipes).");
|
SysPushErrorGeneric("AuProcesses is not the right place for PTY support. At least not in this form (this level of abstraction only cares for pipes).");
|
||||||
break;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fds[0] > 0)
|
||||||
|
{
|
||||||
|
if (!AuIO::SetFDShareAccess(fds[0], bIsRead))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fds[1] > 0)
|
||||||
|
{
|
||||||
|
if (!AuIO::SetFDShareAccess(fds[1], !bIsRead))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Yea, I guess we can't really guard against threads racing to leak close on exec-less fds
|
||||||
|
// Let's just not care on UNIX.
|
||||||
|
// Worst case, we leak a daemons input/output FD to a different daemon of a differing permission level
|
||||||
|
// ...and somehow you can find that fd
|
||||||
|
// ...and probably dup it before ::start()
|
||||||
|
// ...and issue the right commands over the stream to do something bad
|
||||||
|
// Shouldn't need to worry about his for a while.
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProcessImpl::Init()
|
bool ProcessImpl::Init()
|
||||||
{
|
{
|
||||||
InitProcessStdHandles(this->startup_.fwdOut, this->pipeStdOut_);
|
InitProcessStdHandles(this->startup_.fwdOut, this->pipeStdOut_, AuIO::EStandardStream::eOutputStream, this->startup_.handleOutStream);
|
||||||
InitProcessStdHandles(this->startup_.fwdErr, this->pipeStdErr_);
|
InitProcessStdHandles(this->startup_.fwdErr, this->pipeStdErr_, AuIO::EStandardStream::eErrorStream, this->startup_.handleErrorStream);
|
||||||
InitProcessStdHandles(this->startup_.fwdIn, this->pipeStdIn_);
|
InitProcessStdHandles(this->startup_.fwdIn, this->pipeStdIn_, AuIO::EStandardStream::eInputStream, this->startup_.handleInputStream);
|
||||||
|
|
||||||
this->loopSource_ = AuMakeShared<ProcessAliveLoopSource>();
|
this->loopSource_ = AuMakeShared<ProcessAliveLoopSource>();
|
||||||
if (!this->loopSource_)
|
if (!this->loopSource_)
|
||||||
@ -331,7 +409,8 @@ namespace Aurora::Processes
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->fsHandle_->InitFromPairMove(this->pipeStdOut_[0], this->pipeStdIn_[1]);
|
this->fsHandle_->InitFromPairMove(this->pipeStdOut_[0] == -1 ? AuOptionalEx<AuUInt64> {} : AuOptionalEx<AuUInt64> { (AuUInt64)this->pipeStdOut_[0] } ,
|
||||||
|
this->pipeStdIn_[1] == -1 ? AuOptionalEx<AuUInt64> {} : AuOptionalEx<AuUInt64> { (AuUInt64)this->pipeStdIn_[1] });
|
||||||
this->fsStream_->Init(this->fsHandle_);
|
this->fsStream_->Init(this->fsHandle_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,7 +428,7 @@ namespace Aurora::Processes
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->fsErrorHandle_->InitFromPairMove(this->pipeStdErr_[0], -1);
|
this->fsErrorHandle_->InitFromPairMove(this->pipeStdErr_[0] == -1 ? AuOptionalEx<AuUInt64> {} : AuOptionalEx<AuUInt64> { (AuUInt64)this->pipeStdErr_[0] }, {});
|
||||||
this->fsErrorStream_->Init(this->fsErrorHandle_);
|
this->fsErrorStream_->Init(this->fsErrorHandle_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,25 +447,19 @@ namespace Aurora::Processes
|
|||||||
|
|
||||||
void ProcessImpl::ForkMain()
|
void ProcessImpl::ForkMain()
|
||||||
{
|
{
|
||||||
if (this->startup_.fwdIn != EStreamForward::eCurrentProcess)
|
|
||||||
{
|
{
|
||||||
::dup2(pipeStdIn_[0], STDIN_FILENO);
|
::dup2(this->pipeStdIn_[0], STDIN_FILENO);
|
||||||
::close(pipeStdIn_[0]);
|
::close(this->pipeStdIn_[0]);
|
||||||
::close(pipeStdIn_[1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->startup_.fwdErr != EStreamForward::eCurrentProcess)
|
|
||||||
{
|
{
|
||||||
::dup2(pipeStdErr_[1], STDERR_FILENO);
|
::dup2(this->pipeStdErr_[1], STDERR_FILENO);
|
||||||
::close(pipeStdIn_[0]);
|
::close(this->pipeStdErr_[1]);
|
||||||
::close(pipeStdIn_[1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->startup_.fwdOut != EStreamForward::eCurrentProcess)
|
|
||||||
{
|
{
|
||||||
::dup2(pipeStdOut_[1], STDOUT_FILENO);
|
::dup2(this->pipeStdOut_[1], STDOUT_FILENO);
|
||||||
::close(pipeStdIn_[0]);
|
::close(this->pipeStdOut_[1]);
|
||||||
::close(pipeStdIn_[1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(AURORA_IS_LINUX_DERIVED)
|
#if defined(AURORA_IS_LINUX_DERIVED)
|
||||||
@ -421,8 +494,7 @@ namespace Aurora::Processes
|
|||||||
|
|
||||||
if (this->type_ == ESpawnType::eSpawnOvermap)
|
if (this->type_ == ESpawnType::eSpawnOvermap)
|
||||||
{
|
{
|
||||||
::execv(this->startup_.process.c_str(), (char *const *)this->cargs_.data()); // https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html
|
this->ForkMain();
|
||||||
SysPushErrorGen("execv didn't overwrite the process map, given {} ({})", this->startup_.process, this->debug_);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,9 +56,9 @@ namespace Aurora::Processes
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
int pipeStdOut_[2]{};
|
int pipeStdOut_[2] { -1, -1 };
|
||||||
int pipeStdErr_[2]{};
|
int pipeStdErr_[2] { -1, -1 };
|
||||||
int pipeStdIn_ [2]{};
|
int pipeStdIn_ [2] { -1, -1 };
|
||||||
|
|
||||||
bool bDontRelOut_ {};
|
bool bDontRelOut_ {};
|
||||||
bool bDontRelIn_ {};
|
bool bDontRelIn_ {};
|
||||||
|
Loading…
Reference in New Issue
Block a user