[+] Explicit async/blocking read process stdout/err

[*] Fixed missing inherit handles flag
[TODO] consider CREATE_NO_WINDOW flag when refactoring create process object
This commit is contained in:
Reece Wilson 2021-12-24 14:34:55 +00:00
parent 31695ae63b
commit a20bb97128
5 changed files with 80 additions and 12 deletions

View File

@ -26,9 +26,6 @@ namespace Aurora::Processes
/// otherwise returns zero
virtual AuSInt GetExitCode() = 0;
///
/// @param exitOnSpawn atomically destroys the current process <br>
/// some platforms only support this
///
// TODO(Reece): what in the hell this is ugly
virtual bool Start(enum ESpawnType, bool fwdOut, bool fwdErr, bool fwdIn) = 0;
@ -37,6 +34,7 @@ namespace Aurora::Processes
virtual bool TryKill() = 0;
virtual bool Read(bool error, void *buffer, AuUInt32 &len) = 0;
virtual bool Read(void *buffer, AuUInt32 &len, bool errorStream = false, bool nonblock = true);
virtual bool Write(const void *buffer, AuUInt32 len) = 0;
};
}

View File

@ -107,6 +107,8 @@ namespace Aurora::Process
// SELinux gets in the way in some instances
// There is no reason we should be searching for the jre binary
// I'm also not convined pulling a cached apk path is the best thing to do here
// Why should we even bother pulling /system/bin/app_process?
return false;
#elif defined(AURORA_IS_POSIX_DERIVED)

View File

@ -323,6 +323,9 @@ namespace Aurora::Process
#endif
#if defined(AURORA_IS_MODERNNT_DERIVED)
// Still doesnt stop hotswaps, and idc
// Glitching would require software to time the attack
// ...requiring a certain degree of access (code execution) + effort
AuWin32CloseHandle(mitigateTimeOfUse);
#endif

View File

@ -46,7 +46,9 @@ namespace Aurora::Processes
AuSInt GetExitCode() override;
bool Read (bool error, void *buffer, AuUInt32 &len) override;
bool Read(bool error, void *buffer, AuUInt32 &len) override;
bool Read(void *buffer, AuUInt32 &len, bool errorStream, bool nonblock) override;
bool Write(const void *buffer, AuUInt32 len) override;
bool Start(enum ESpawnType type, bool fwdOut, bool fwdErr, bool fwdIn) override;
@ -160,12 +162,41 @@ namespace Aurora::Processes
}
bool ProcessImpl::Read(bool error, void *buffer, AuUInt32 &len)
{
return Read(buffer, len, error, false);
}
bool ProcessImpl::Read(void *buffer, AuUInt32 &len, bool errorStream, bool nonblock)
{
len = 0;
auto handle = error ? pipeStdErr_[0] : pipeStdOut_[0];
if (handle < 0) return false;
auto handle = errorStream ? pipeStdErr_[0] : pipeStdOut_[0];
if (handle < 0)
{
return false;
}
auto control = fcntl(fd, F_GETFL);
auto ref = control;
if (nonblock)
{
control |= O_NONBLOCK;
}
else
{
control &= ~O_NONBLOCK;
}
if (ref != control)
{
fcntl(fd, F_SETFL, control);
}
auto tmp = read(handle, buffer, len);
if (tmp < 0) return false;
if (tmp < 0)
{
return false;
}
len = tmp;
return true;
}

View File

@ -54,6 +54,8 @@ namespace Aurora::Processes
void ShutdownPipes();
bool Read(bool error, void *buffer, AuUInt32 &len) override;
bool Read(void *buffer, AuUInt32 &len, bool errorStream, bool nonblock) override;
bool Write(const void *buffer, AuUInt32 len) override;
// TODO: what in the hell this is ugly
@ -211,10 +213,36 @@ namespace Aurora::Processes
}
bool ProcessImpl::Read(bool error, void *buffer, AuUInt32 &len)
{
return Read(buffer, len, error, false);
}
bool ProcessImpl::Read(void *buffer, AuUInt32 &len, bool errorStream, bool nonblock)
{
DWORD size = std::exchange(len, 0);
auto handle = error ? pipeStdErrRead_ : pipeStdOutRead_;
if (handle == INVALID_HANDLE_VALUE) return false;
auto handle = errorStream ? pipeStdErrRead_ : pipeStdOutRead_;
if (handle == INVALID_HANDLE_VALUE)
{
return false;
}
if (nonblock)
{
DWORD avail {};
if (!PeekNamedPipe(handle, NULL, NULL, NULL, &avail, NULL))
{
return false;
}
if (!avail)
{
return true;
}
size = std::min(size, avail);
}
auto ret = ReadFile(handle, buffer, size, &size, NULL);
len = size;
return ret;
@ -288,15 +316,17 @@ namespace Aurora::Processes
{
STARTUPINFOW startupInfo = { 0 };
startupInfo.cb = sizeof(startupInfo);
bool inheritHandles = fwdIn || fwdErr || fwdOut;
startupInfo.hStdInput = pipeStdInRead_;
startupInfo.hStdError = pipeStdErrWrite_;
startupInfo.hStdOutput = pipeStdOutWrite_;
startupInfo.dwFlags |= ((fwdIn || fwdErr || fwdOut) ? STARTF_USESTDHANDLES : 0);
startupInfo.dwFlags |= (inheritHandles ? STARTF_USESTDHANDLES : 0);
auto result = CreateProcessW(Locale::ConvertFromUTF8(this->execModule_).c_str(),
Locale::ConvertFromUTF8(this->windowsCli_).data(),
NULL, NULL, FALSE,
NULL, NULL, inheritHandles,
NULL,
NULL, NULL, &startupInfo, &processInfo);
@ -309,6 +339,10 @@ namespace Aurora::Processes
this->process_ = processInfo.hProcess;
this->hthread_ = processInfo.hThread;
AuWin32CloseHandle(this->pipeStdOutRead_);
AuWin32CloseHandle(this->pipeStdErrRead_);
AuWin32CloseHandle(this->pipeStdInWrite_);
if (type == ESpawnType::eSpawnChildProcessWorker)
{
if (gLeaderJob)