[TODO: BLOCK 2 PROGRESS]

This commit is contained in:
Reece Wilson 2022-06-14 02:14:51 +01:00
parent 0a2d4cde04
commit f166849e9f
14 changed files with 316 additions and 64 deletions

View File

@ -0,0 +1,9 @@
# AuExit
Provides termination events, usually on a worker thread, when application termination is likely. Event categories include: control c, an exception was thrown, application shutdown.
Trigger Levels:
* eSafeTermination (safe unload)
* eFatalException (a fatal exception, math, or memory error occurred)
* eSigTerminate (control + c)
* eProblematicEvent (an exception was thrown or some other fatal condition. should probably flush & sync streams or invalidate caches.)

View File

@ -11,62 +11,129 @@ namespace Aurora::IO
{ {
struct IIOPipeInterceptor; struct IIOPipeInterceptor;
struct IPipeFrames
{
/**
* @brief pipe starting hook
*/
virtual void OnStart() = 0;
/**
* @brief This function is called once the stream reader returns zero
* You should use this opportunity to schedule the next waitable item state (eg, initiate async read, set event high, etc)
* You can return false to soft-fail the pipe to indicate EoS
* You should otherwise return true in order to continue yield until the next waitable item state change
* Note, an EoS event may also occur during the next alert state change should the stream reader return an error
*/
virtual void OnEndPump() = 0;
/**
* @brief pipe shutdown hook
*/
virtual void OnEnd(bool fatal) = 0;
};
struct IOPipeData struct IOPipeData
{ {
/**
* @brief IO events
*/
AuSPtr<IIOWaitableItem> watchItem; AuSPtr<IIOWaitableItem> watchItem;
/**
* @brief Input source
*/
AuSPtr<IStreamReader> reader; AuSPtr<IStreamReader> reader;
/**
* @brief Output drain
*/
AuSPtr<IStreamWriter> writer; AuSPtr<IStreamWriter> writer;
/**
* @brief Callbacks
*/
AuSPtr<IPipeFrames> frames;
/**
* @brief Enables aggressive stream consumption, allowing for bias towards clients if they were to send a lot of data (including dos)
* Instead of reading the input stream once, so long as the output stream written paremeter yields a non-zero number, bytes
* will continue to pump through the writer. Breakdown of the pipe is expected on reader oversaturation as defined by the
* IOPipeRequest
*/
bool bShouldReadUntilZero {};
}; };
struct IOPipeRequest struct IOPipeRequest
{ {
/** /**
* @brief The two streams to join and an invokable object * @brief Amount of bytes to transfer or zero if stream
*/
IOPipeData data;
/**
* @brief Amount of bytes to transfer
*/ */
AuUInt32 lengthOrZero {}; AuUInt32 lengthOrZero {};
/**
* @brief internal frame size or zero if fallback
*/
AuUInt32 pageLengthOrZero {};
/** /**
* @brief event listener * @brief event listener
*/ */
AuSPtr<IIOPipeEventListener> listener; AuSPtr<IIOPipeEventListener> listener;
/** /**
* @brief Used as the buffer size for streams of length 0 * @brief Used as the buffer size for streams of page length 0
*/ */
AuUInt32 fallbackPageSize {4096 * 50}; AuUInt32 fallbackPageSize {4096 * 50};
AuSPtr<IIOPipeInterceptor> processor; AuSPtr<IIOPipeInterceptor> processor;
}; };
struct IOPipeRequestBasic : IOPipeRequest
{
/**
* @brief The two streams to join and an invokable object
*/
IOPipeData data;
};
struct IOPipeRequestAIO : IOPipeRequest
{
AuSPtr<IAsyncTransaction> asyncTransaction;
AuSPtr<IStreamWriter> writer;
bool shouldReadUntilZero;
};
struct IIOPipeWork
{
/**
* @brief
* @return false should no IIOPipeEventListener event ever be fired. you should generally expect callback based failure.
*/
virtual bool Start() = 0;
virtual bool End() = 0;
};
/** /**
* @brief Different operating systems implement high level stream copy abstraction between network, file, and/or file descriptors. * @brief Different operating systems implement high level stream copy abstraction between network, file, and/or file descriptors.
* This interface connects arbitrary stream objects to one another by piping data under an iprocessor tick; or delegates * This interface connects arbitrary stream objects to one another by piping data under an iprocessor tick; or delegates
* such task to the operating system, if possible. * such task to the operating system, if possible.
*/ */
struct IIOPipeProcessor struct IIOPipeProcessor
{ {
/** /**
* @brief * @brief
* @param request * @param request
* @return * @return
*/ */
virtual bool BeginPipe(const IOPipeRequest &request) = 0; virtual AuSPtr<IIOPipeWork> NewBasicPipe(const IOPipeRequestBasic &request) = 0;
/**
* @brief
* @param itm
*/
virtual void EndByWatch(const AuSPtr<IIOWaitableItem> &itm) = 0;
/** /**
* @brief * @brief
* @param itm
*/ */
virtual void EndByListener(const AuSPtr<IIOPipeEventListener> &itm) = 0; virtual AuSPtr<IIOPipeWork> NewAIOPipe(const IOPipeRequestAIO &request) = 0;
}; };
} }

View File

@ -0,0 +1,12 @@
# AuMemory
Example Usage: \
File: HelloAurora/master/Tests/Public/15. Hello ByteBuffer/Main.cpp
# Features
* ByteBuffer
* Optimize cache [heavy precache]
* O(1) Heap Allocator (based on a hacked up external lib)
* Purge Executable Memory Cache
* Pin virtual memory into physical memory / SwapLock

View File

@ -0,0 +1,17 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: EStreamForward.hpp
Date: 2022-6-13
Author: Reece
***/
#pragma once
namespace Aurora::Processes
{
AUE_DEFINE(EStreamForward, (
eNull,
eCurrentProcess,
eAsyncPipe
));
}

View File

@ -9,6 +9,7 @@
#include "ESpawnType.hpp" #include "ESpawnType.hpp"
#include "EStandardHandle.hpp" #include "EStandardHandle.hpp"
#include "EStreamForward.hpp"
#include "IProcess.hpp" #include "IProcess.hpp"
#include "StartupParmaters.hpp" #include "StartupParmaters.hpp"
#include "Spawn.hpp" #include "Spawn.hpp"

View File

@ -31,23 +31,30 @@ namespace Aurora::Processes
/** /**
* @brief Enables stdout ipc to parent * @brief Enables stdout ipc to parent
*/ */
bool fwdOut {}; EStreamForward fwdOut {};
/** /**
* @brief Enables stderr ipc to parent * @brief Enables stderr ipc to parent
*/ */
bool fwdErr {}; EStreamForward fwdErr {};
/** /**
* @brief Enables stdin ipc from parent (us) to child * @brief Enables stdin ipc from parent (us) to child
*/ */
bool fwdIn {}; EStreamForward fwdIn {};
/** /**
* @brief Effectively is user facing. * @brief Effectively is user facing.
* Under Windows GUI, this means hides conhost. * Under Windows GUI, this means hides conhost.
* Under ConsoleApps, this means blank the childs output handles. * Under ConsoleApps, this means blank the childs output handles.
*/ */
bool noShowConsole {}; bool bNoShowConsole {};
/**
* @brief Starts the process in a resumable suspension mode
*/
bool bInDebugMode {};
AuOptional<AuString> workingDirectory;
}; };
} }

View File

@ -0,0 +1,12 @@
# AuRng
Example Usage: HelloAurora/master/Tests/Public/14. Hello RNG/Main.cpp
# Features
* Static and IRandomDevice RNG routines
* Partial template support for arrays and strings
* Various numeric operations (int range, 0-1 decimal, string of character set, next word, etc)
# Backends
* System provided CSRNG backend
* WELL fast backend; seeded by U32's, U64's, and larger WELL blob's

View File

@ -27,6 +27,11 @@ namespace Aurora::IO
bool IOProcessor::Init() bool IOProcessor::Init()
{ {
if (!this->ToQueue())
{
return {};
}
if (!this->items.Init()) if (!this->items.Init())
{ {
SysPushErrorNested(); SysPushErrorNested();
@ -39,6 +44,8 @@ namespace Aurora::IO
return false; return false;
} }
this->ToQueue()->SourceAdd(this->items.cvEvent);
return true; return true;
} }
@ -119,6 +126,7 @@ namespace Aurora::IO
AU_LOCK_GUARD(this->items.mutex); AU_LOCK_GUARD(this->items.mutex);
FrameStart(); FrameStart();
FrameWaitForAny(0); FrameWaitForAny(0);
FramePumpWaitingBlocked();
FrameRunThreadIO(); FrameRunThreadIO();
FrameRunCheckLSes(); FrameRunCheckLSes();
return FrameRunEpilogue(); return FrameRunEpilogue();
@ -425,17 +433,21 @@ namespace Aurora::IO
} }
} }
void IOProcessor::FramePumpWaitingBlocked()
{
auto blocked = this->items.GetBlockedSignals();
if (blocked.size())
{
this->items.workSignaled.insert(this->items.workSignaled.end(), blocked.begin(), blocked.end());
}
}
void IOProcessor::FrameStart() void IOProcessor::FrameStart()
{ {
ReportState(EIOProcessorEventStage::eFrameStartOfFrame); ReportState(EIOProcessorEventStage::eFrameStartOfFrame);
this->bFrameStart = true; this->bFrameStart = true;
auto blocked = this->items.GetBlockedSignals(); FramePumpWaitingBlocked();
if (blocked.size())
{
AU_LOCK_GUARD(this->items.mutex);
this->items.workSignaled.insert(this->items.workSignaled.end(), blocked.begin(), blocked.end());
}
} }
void IOProcessor::FrameRunThreadIO() void IOProcessor::FrameRunThreadIO()
@ -544,13 +556,24 @@ namespace Aurora::IO
void IOProcessor::CancelWorkItem() void IOProcessor::CancelWorkItem()
{ {
if (!this->workItem)
{
return;
}
this->workItem->Cancel(); this->workItem->Cancel();
this->workItem.reset(); this->workItem.reset();
} }
void IOProcessor::RemoveLSTimer() void IOProcessor::RemoveLSTimer()
{ {
this->ToQueue()->SourceRemove(this->timers.lsTicker); auto queue = this->ToQueue();
if (!queue)
{
return;
}
queue->SourceRemove(this->timers.lsTicker);
} }
bool IOProcessor::IsAsync() bool IOProcessor::IsAsync()
@ -658,7 +681,17 @@ namespace Aurora::IO
void IOProcessor::ReleaseAllWatches() void IOProcessor::ReleaseAllWatches()
{ {
RemoveTimer();
auto queue = ToQueue();
if (queue)
{
if (this->items.cvEvent)
{
queue->SourceRemove(this->items.cvEvent);
}
queue->Commit();
}
} }
bool IOProcessor::HasItems() bool IOProcessor::HasItems()

View File

@ -33,7 +33,8 @@ namespace Aurora::IO
bool AddEventListener(const AuSPtr<IIOProcessorEventListener> &eventListener) override; bool AddEventListener(const AuSPtr<IIOProcessorEventListener> &eventListener) override;
void RemoveEventListener(const AuSPtr<IIOProcessorEventListener> &eventListener) override; void RemoveEventListener(const AuSPtr<IIOProcessorEventListener> &eventListener) override;
void FrameStart(); void FrameStart();
void FramePumpWaitingBlocked();
bool FrameWaitForAny(AuUInt32 msMax); bool FrameWaitForAny(AuUInt32 msMax);
AuUInt FrameRunEpilogue(); AuUInt FrameRunEpilogue();
void FrameRunThreadIO(); void FrameRunThreadIO();
@ -102,6 +103,7 @@ namespace Aurora::IO
AuThreadPrimitives::SpinLock listenersSpinLock; AuThreadPrimitives::SpinLock listenersSpinLock;
AuList<AuSPtr<IIOProcessorEventListener>> listeners; AuList<AuSPtr<IIOProcessorEventListener>> listeners;
bool bFrameStart {}; bool bFrameStart {};
}; };
} }

View File

@ -9,6 +9,7 @@
#include <Aurora/IO/IOExperimental.hpp> #include <Aurora/IO/IOExperimental.hpp>
#include "IOProcessorItem.hpp" #include "IOProcessorItem.hpp"
#include "IOProcessorItems.hpp" #include "IOProcessorItems.hpp"
#include "IOProcessor.hpp"
namespace Aurora::IO namespace Aurora::IO
{ {
@ -17,6 +18,8 @@ namespace Aurora::IO
this->mutex = AuThreadPrimitives::CriticalSectionUnique(); this->mutex = AuThreadPrimitives::CriticalSectionUnique();
this->mutex2 = AuThreadPrimitives::CriticalSectionUnique(); this->mutex2 = AuThreadPrimitives::CriticalSectionUnique();
this->cvEvent = AuLoop::NewLSEvent(false, true, true);
return bool(this->mutex) && bool(this->mutex2); return bool(this->mutex) && bool(this->mutex2);
} }
@ -31,6 +34,7 @@ namespace Aurora::IO
if (!AddFrameTemp(item)) if (!AddFrameTemp(item))
{ {
AU_LOCK_GUARD(this->mutex2); AU_LOCK_GUARD(this->mutex2);
this->cvEvent->Set();
return AuTryInsert(this->workSignaled2, item); return AuTryInsert(this->workSignaled2, item);
} }

View File

@ -14,6 +14,8 @@ namespace Aurora::IO
struct IOProcessorItems struct IOProcessorItems
{ {
AuSPtr<AuLoop::ILSEvent> cvEvent;
AuList<AuSPtr<IOProcessorItem>> allItems; AuList<AuSPtr<IOProcessorItem>> allItems;
AuList<AuSPtr<IOProcessorItem>> onTickReceivers; AuList<AuSPtr<IOProcessorItem>> onTickReceivers;
AuList<AuSPtr<IOProcessorItem>> onOtherReceivers; AuList<AuSPtr<IOProcessorItem>> onOtherReceivers;

View File

@ -146,9 +146,7 @@ namespace Aurora::Processes
void ProcessImpl::ShutdownPipes() void ProcessImpl::ShutdownPipes()
{ {
AuWin32CloseHandle(this->pipeStdOutWrite_); RelOtherHandles();
AuWin32CloseHandle(this->pipeStdErrWrite_);
AuWin32CloseHandle(this->pipeStdInRead_);
//AuWin32CloseHandle(this->pipeStdOutRead_); //AuWin32CloseHandle(this->pipeStdOutRead_);
//AuWin32CloseHandle(this->pipeStdErrRead_); //AuWin32CloseHandle(this->pipeStdErrRead_);
//AuWin32CloseHandle(this->pipeStdInWrite_); //AuWin32CloseHandle(this->pipeStdInWrite_);
@ -238,9 +236,14 @@ namespace Aurora::Processes
} }
this->exitCode_ = 0x10110100; this->exitCode_ = 0x10110100;
if (this->startup_.fwdOut) if (this->startup_.fwdOut == EStreamForward::eAsyncPipe)
{ {
if (!CreatePipeEx(&pipeStdOutRead_, &pipeStdOutWrite_, &saAttr, 0, FILE_FLAG_OVERLAPPED, 0)) if (!CreatePipeEx(&this->pipeStdOutRead_,
&this->pipeStdOutWrite_,
&saAttr,
0,
FILE_FLAG_OVERLAPPED,
0))
{ {
return false; return false;
} }
@ -250,36 +253,81 @@ namespace Aurora::Processes
return false; return false;
} }
} }
else if (this->startup_.fwdOut == EStreamForward::eCurrentProcess)
if (this->startup_.fwdErr)
{ {
if (!CreatePipeEx(&pipeStdErrRead_, &pipeStdErrWrite_, &saAttr, 0, FILE_FLAG_OVERLAPPED, 0)) HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
if (handle != INVALID_HANDLE_VALUE && handle)
{
SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 1);
this->bDontRelOut_ = true;
this->pipeStdOutWrite_ = handle;
}
}
if (this->startup_.fwdErr == EStreamForward::eAsyncPipe)
{
if (!CreatePipeEx(&this->pipeStdErrRead_,
&this->pipeStdErrWrite_,
&saAttr,
0,
FILE_FLAG_OVERLAPPED,
0))
{ {
return false; return false;
} }
if (!SetHandleInformation(pipeStdErrRead_, HANDLE_FLAG_INHERIT, 0)) if (!SetHandleInformation(this->pipeStdErrRead_, HANDLE_FLAG_INHERIT, 0))
{ {
return false; return false;
} }
} }
else if (this->startup_.fwdErr == EStreamForward::eCurrentProcess)
if (this->startup_.fwdIn)
{ {
if (!CreatePipeEx(&pipeStdInRead_, &pipeStdInWrite_, &saAttr, 0, 0, FILE_FLAG_OVERLAPPED)) HANDLE handle = GetStdHandle(STD_ERROR_HANDLE);
if (handle != INVALID_HANDLE_VALUE && handle)
{
SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 1);
this->bDontRelErr_ = true;
this->pipeStdErrWrite_ = handle;
}
}
if (this->startup_.fwdIn == EStreamForward::eAsyncPipe)
{
if (!CreatePipeEx(&this->pipeStdInRead_,
&this->pipeStdInWrite_,
&saAttr,
0,
0,
FILE_FLAG_OVERLAPPED))
{ {
return false; return false;
} }
if (!SetHandleInformation(pipeStdInWrite_, HANDLE_FLAG_INHERIT, 0)) if (!SetHandleInformation(this->pipeStdInWrite_, HANDLE_FLAG_INHERIT, 0))
{ {
return false; return false;
} }
} }
else if (this->startup_.fwdIn == EStreamForward::eCurrentProcess)
if (this->startup_.noShowConsole)
{ {
HANDLE nulFile = INVALID_HANDLE_VALUE; HANDLE handle = GetStdHandle(STD_ERROR_HANDLE);
if (handle != INVALID_HANDLE_VALUE && handle)
{
SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 1);
this->bDontRelIn_ = true;
this->pipeStdInRead_ = handle;
}
}
{
HANDLE nulFile;
#define NEW_NULL_HANDLE \ #define NEW_NULL_HANDLE \
{ \ { \
@ -306,7 +354,7 @@ namespace Aurora::Processes
} }
} }
if (this->startup_.fwdIn || this->startup_.fwdOut) if (this->startup_.fwdIn == EStreamForward::eAsyncPipe || this->startup_.fwdOut == EStreamForward::eAsyncPipe)
{ {
this->fsHandle_ = AuMakeShared<IO::FS::FileHandle>(); this->fsHandle_ = AuMakeShared<IO::FS::FileHandle>();
if (!this->fsHandle_) if (!this->fsHandle_)
@ -324,7 +372,7 @@ namespace Aurora::Processes
this->fsStream_->Init(this->fsHandle_); this->fsStream_->Init(this->fsHandle_);
} }
if (this->startup_.fwdErr) if (this->startup_.fwdErr == EStreamForward::eAsyncPipe)
{ {
this->fsErrorHandle_ = AuMakeShared<IO::FS::FileHandle>(); this->fsErrorHandle_ = AuMakeShared<IO::FS::FileHandle>();
if (!this->fsErrorHandle_) if (!this->fsErrorHandle_)
@ -374,18 +422,29 @@ namespace Aurora::Processes
STARTUPINFOW startupInfo = { 0 }; STARTUPINFOW startupInfo = { 0 };
startupInfo.cb = sizeof(startupInfo); startupInfo.cb = sizeof(startupInfo);
bool inheritHandles = this->startup_.fwdIn || this->startup_.fwdErr || this->startup_.fwdOut || this->startup_.noShowConsole; startupInfo.hStdInput = this->pipeStdInRead_;
startupInfo.hStdError = this->pipeStdErrWrite_;
startupInfo.hStdOutput = this->pipeStdOutWrite_;
startupInfo.dwFlags |= STARTF_USESTDHANDLES;
startupInfo.hStdInput = pipeStdInRead_; auto cwd = this->startup_.workingDirectory;
startupInfo.hStdError = pipeStdErrWrite_; std::wstring wcwd;
startupInfo.hStdOutput = pipeStdOutWrite_; if (cwd)
startupInfo.dwFlags |= (inheritHandles ? STARTF_USESTDHANDLES : 0); {
wcwd = Locale::ConvertFromUTF8(this->windowsCli_);
if (!wcwd.size())
{
SysPushErrorMem();
return false;
}
}
auto result = CreateProcessW(Locale::ConvertFromUTF8(this->startup_.process).c_str(), auto result = CreateProcessW(Locale::ConvertFromUTF8(this->startup_.process).c_str(),
Locale::ConvertFromUTF8(this->windowsCli_).data(), Locale::ConvertFromUTF8(this->windowsCli_).data(),
NULL, NULL, inheritHandles, NULL, NULL, true,
this->startup_.noShowConsole ? CREATE_NO_WINDOW : NULL, // yea we can keep CREATE_NO_WINDOW on for non-console apps. its legal -> https://docs.microsoft.com/en-us/windows/win32/procthread/process-creation-flags (this->startup_.bNoShowConsole ? CREATE_NO_WINDOW : NULL) | // yea we can keep CREATE_NO_WINDOW on for non-console apps. its legal -> https://docs.microsoft.com/en-us/windows/win32/procthread/process-creation-flags
NULL, NULL, &startupInfo, &processInfo); (this->startup_.bInDebugMode ? CREATE_SUSPENDED : NULL),
NULL, wcwd.size() ? wcwd.data() : nullptr, &startupInfo, &processInfo);
if (!result) if (!result)
{ {
@ -397,9 +456,7 @@ namespace Aurora::Processes
this->process_ = processInfo.hProcess; this->process_ = processInfo.hProcess;
this->hthread_ = processInfo.hThread; this->hthread_ = processInfo.hThread;
AuWin32CloseHandle(this->pipeStdOutWrite_); RelOtherHandles();
AuWin32CloseHandle(this->pipeStdErrWrite_);
AuWin32CloseHandle(this->pipeStdInRead_);
if (this->type_ == ESpawnType::eSpawnChildProcessWorker) if (this->type_ == ESpawnType::eSpawnChildProcessWorker)
{ {
@ -409,7 +466,7 @@ namespace Aurora::Processes
} }
} }
// TODO: delegate to a singular worker thread // TODO: delegate to a singular worker thread / SetThreadPoolWait
auto a = [=]() auto a = [=]()
{ {
WaitForSingleObject(processInfo.hProcess, INFINITE); WaitForSingleObject(processInfo.hProcess, INFINITE);
@ -439,6 +496,25 @@ namespace Aurora::Processes
return true; return true;
} }
void ProcessImpl::RelOtherHandles()
{
if (!this->bDontRelOut_)
{
AuWin32CloseHandle(this->pipeStdOutWrite_);
}
if (!this->bDontRelErr_)
{
AuWin32CloseHandle(this->pipeStdErrWrite_);
}
if (!this->bDontRelIn_)
{
AuWin32CloseHandle(this->pipeStdInRead_);
}
}
AUKN_SYM IProcess *SpawnNew(const StartupParmaters &params) AUKN_SYM IProcess *SpawnNew(const StartupParmaters &params)
{ {
try try

View File

@ -40,6 +40,8 @@ namespace Aurora::Processes
bool Init(); bool Init();
void RelOtherHandles();
private: private:
HANDLE pipeStdOutRead_ {INVALID_HANDLE_VALUE}; HANDLE pipeStdOutRead_ {INVALID_HANDLE_VALUE};
@ -49,6 +51,12 @@ namespace Aurora::Processes
HANDLE pipeStdInRead_ {INVALID_HANDLE_VALUE}; HANDLE pipeStdInRead_ {INVALID_HANDLE_VALUE};
HANDLE pipeStdInWrite_ {INVALID_HANDLE_VALUE}; HANDLE pipeStdInWrite_ {INVALID_HANDLE_VALUE};
bool bDontRelOut_ {};
bool bDontRelIn_ {};
bool bDontRelErr_ {};
AuSPtr<AuLoop::ILoopSource> loopSource_; AuSPtr<AuLoop::ILoopSource> loopSource_;
AuSPtr<IO::FS::FileHandle> fsHandle_; AuSPtr<IO::FS::FileHandle> fsHandle_;

View File

@ -339,6 +339,7 @@ namespace Aurora::Processes
pid_t pid; pid_t pid;
{ {
// TODO: clone without CLONE_FS and CLONE_THREAD (if non-sid path)
pid = ::fork(); pid = ::fork();
if (pid == 0) if (pid == 0)
@ -369,7 +370,8 @@ namespace Aurora::Processes
{ {
::setsid(); ::setsid();
} }
// TODO: pthread_chdir_np on OSX
::execv(this->startup_.process.c_str(), (char * const *)this->cargs_.data()); // https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html ::execv(this->startup_.process.c_str(), (char * const *)this->cargs_.data()); // https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html
SysPushErrorGen("execv didn't overwrite the process map. Launch: {} ({})", this->startup_.process, this->debug_); SysPushErrorGen("execv didn't overwrite the process map. Launch: {} ({})", this->startup_.process, this->debug_);
@ -396,7 +398,7 @@ namespace Aurora::Processes
this->alive_ = true; this->alive_ = true;
{ {
AU_LOCK_GUARD(gRWLock->AsWritable()); AU_LOCK_GUARD(gRWLock->AsWritable());\
SysAssert(AuTryInsert(gPidLookupMap, pid, this)); SysAssert(AuTryInsert(gPidLookupMap, pid, this));
} }