[*] More async api change

[*] Improve win32 exception watcher
[*] Fix early pin reset. Possible use after write still, unsure if self reference is legal
This commit is contained in:
Reece Wilson 2021-10-23 12:36:14 +01:00
parent a679ecb534
commit 3d859a319e
4 changed files with 94 additions and 57 deletions

View File

@ -140,6 +140,28 @@ namespace Aurora::Async
return ret;
}
template<class Info_t = AVoid, class Result_t = AVoid, class BaseInfo_t = AVoid, class BaseResult_t = AVoid>
static inline FJob<Info_t, Result_t> JobFromDerivedJob(const FJob<BaseInfo_t, BaseResult_t> &reference)
{
FJob<Info_t, Result_t> ret;
ret.onSuccess = [=](const Info_t &in, const Result_t &a)
{
if (reference.onSuccess)
{
reference.onSuccess(in, a);
}
};
ret.onFailure = [=](const Info_t &a)
{
if (reference.onFailure)
{
reference.onSuccess(a);
}
};
return ret;
}
using FVoidJob = FJob<AVoid, AVoid>;
template<class Info_t = AVoid, class Result_t = AVoid>
@ -176,13 +198,13 @@ namespace Aurora::Async
return ret;
}
template<typename Info_t = AVoid, typename Out_t = AVoid, class ClazzImpl>
FTask<Info_t, Out_t> TaskFromVoidVoid(AuVoidFunc &&func)
template<typename Info_t = AVoid, typename Out_t = AVoid>
FTask<Info_t, Out_t> TaskFromVoidVoid(const AuVoidFunc &func)
{
FTask<Info_t, Out_t> ret;
ret.onFrame = [callable = func](const Info_t &in) -> Out_t
{
func();
callable();
return {};
};
return ret;
@ -659,6 +681,18 @@ namespace Aurora::Async
return Async::DispatchBasicWorkCallback<Info_t, Result_t, Task_t, Job_t>(worker, Async::TaskFromConsumerRefT<Info_t, Result_t>(task), job, inputParameters, enableWait);
}
template<typename Info_t = AVoid, typename Result_t = AVoid, typename Task_t = FTask<Info_t, Result_t>, typename Job_t = FJob<Info_t, Result_t>, typename ClazzImpl>
AuSPtr<Aurora::Async::IWorkItem> DispatchFunctor(const WorkerId_t &worker, ClazzImpl task, const Job_t &job, const Info_t &inputParameters, bool enableWait = false)
{
return Async::DispatchBasicWorkCallback<Info_t, Result_t, Task_t, Job_t>(worker, Async::TaskFromConsumerRefT<Info_t, Result_t>(task), job, inputParameters, enableWait);
}
template<typename Info_t = AVoid, typename Result_t = AVoid, typename Task_t = FTask<Info_t, Result_t>, typename Job_t = FJob<Info_t, Result_t>, typename ClazzImpl>
AuSPtr<Aurora::Async::IWorkItem> DispatchVoid(const WorkerId_t &worker, ClazzImpl task, const Job_t &job, const Info_t &inputParameters, bool enableWait = false)
{
return Async::DispatchBasicWorkCallback<Info_t, Result_t, Task_t, Job_t>(worker, Async::TaskFromVoidVoid<Info_t, Result_t>(task), job, inputParameters, enableWait);
}
#undef ASYNC_ERROR
#undef ASYNC_FINISH

View File

@ -105,14 +105,14 @@ namespace Aurora::Console::Commands
}
else
{
Async::DispatchBasicWorkCallback<CommandDispatch, Async::AVoid>(workerId,
Async::TaskFromConsumerRefT<CommandDispatch, Async::AVoid>([](const CommandDispatch &dispatch) -> AuOptional<Async::AVoid>
Async::DispatchBasicWorkCallback<CommandDispatch>(workerId,
Async::TaskFromConsumerRefT<CommandDispatch>([](const CommandDispatch &dispatch) -> void
{
dispatch.callback->onCommand(dispatch.arguments);
return {};
}),
{},
CommandDispatch(res.result, callback)
CommandDispatch(res.result, callback),
false
);
}

View File

@ -186,6 +186,9 @@ namespace Aurora::Debug
void InitWin32()
{
static AuString kStringRawName = typeid(AuString).raw_name();
#if defined(DEBUG) || defined(STAGING)
SymInitialize(GetCurrentProcess(), NULL, TRUE);
#endif
@ -234,61 +237,62 @@ namespace Aurora::Debug
handle = reinterpret_cast<HMODULE>(ExceptionInfo->ExceptionRecord->ExceptionInformation[3]);
}
const auto catchableTypeArray = reinterpret_cast<const CatchableTypeArray*>(reinterpret_cast<AuUInt>(handle) + static_cast<AuUInt>(throwInfo->pCatchableTypeArray));
const auto type = reinterpret_cast<CatchableType*> (reinterpret_cast<AuUInt>(handle) + static_cast<AuUInt>(catchableTypeArray->arrayOfCatchableTypes[0]));
const auto descriptor = reinterpret_cast<TypeDescriptor*> (reinterpret_cast<AuUInt>(handle) + static_cast<AuUInt>(type->pType));
// .?AVException and .?AVexception follow the same abi of const char * at pos 0 (__std_exception_data) after a vtable ptr of i dont care to define how many functions
// odds are, these assumptions about the ABI will never break. the QOL improvement of knowing of who is farting in my address space far exceeds an issue under win 720 targets 10 years in the future
if (strnicmp(descriptor->name, ".?AVException@", AuArraySize(".?AVException@") - 1) == 0)
{
auto exception = reinterpret_cast<std::exception *>(ExceptionInfo->ExceptionRecord->ExceptionInformation[1]);
if (IsReadable(exception))
const auto catchableTypeArray = reinterpret_cast<const CatchableTypeArray*>(reinterpret_cast<AuUInt>(handle) + static_cast<AuUInt>(throwInfo->pCatchableTypeArray));
AuString suffix;
bool derivedFromException = {};
for (int i = 0; i < catchableTypeArray->nCatchableTypes; i++)
{
entry.wincxx.str = exception->what();
}
}
else if (((type->properties & CT_IsSimpleType) != 0) &&
((type->properties & CT_IsWinRTHandle) == 0))
const auto type = reinterpret_cast<CatchableType *> (reinterpret_cast<AuUInt>(handle) + static_cast<AuUInt>(catchableTypeArray->arrayOfCatchableTypes[i]));
const auto descriptor = reinterpret_cast<std::type_info *> (reinterpret_cast<AuUInt>(handle) + static_cast<AuUInt>(type->pType));
entry.wincxx.str += (i == 0 ? "" : AuString(", ")) + descriptor->name();
if (strnicmp(descriptor->raw_name(), ".?AVException@", AuArraySize(".?AVException@") - 1) == 0)
{
derivedFromException = true;
}
else if (strncmp(descriptor->raw_name(), ".PEAD", AuArraySize(".PEAD") - 1) == 0)
{
// assert descriptor->name == ".PEAD"? `DEAP.`?
auto possibleStringPointer = reinterpret_cast<const char **>(ExceptionInfo->ExceptionRecord->ExceptionInformation[1]);
if (IsReadable(possibleStringPointer))
{
auto string = *possibleStringPointer;
// Not a string? I don't care, it has a null byte under 1k in a readable page
if (IsReadable(string) && (strnlen(string, 4096) < 1024))
{
entry.wincxx.str = string;
if (suffix.size()) suffix += ", ";
suffix += string;
}
}
}
//else if (strnicmp(descriptor->name, ".?AV", AuArraySize(".?AV") - 1) == 0)
//{
// /* Annoying
// https://blog.quarkslab.com/visual-c-rtti-inspection.html
// This structure is very important to identify an object since it contains its VFT (field pVFTable) and its mangled name. That's why it usually starts with ".?AV", which means "a C++ class". These structures are stored in the section ".data".
// We decided to do pattern matching on ".?AV" to get the field name of _TypeInformation and thus retrieves the RTTICompleteObjectLocator.
// ... we would then have to traverse the hierarchy to determine the root most signature (std::exceptions vtable hash)
// TODO(Reece): fix me, this is evil and shouldn't make it into the wild
// Fix before 1.0
// */
//
// auto exception = reinterpret_cast<std::exception *>(ExceptionInfo->ExceptionRecord->ExceptionInformation[1]);
// if (IsReadable(exception))
// {
// entry.wincxx.str = exception->what();
// }
//}
else if (strlen(descriptor->name) == 0)
else if (strncmp(descriptor->raw_name(), kStringRawName.data(), kStringRawName.size()) == 0)
{
auto exception = reinterpret_cast<std::exception *>(ExceptionInfo->ExceptionRecord->ExceptionInformation[1]);
if (IsReadable(exception))
auto possibleStdStringPointer = reinterpret_cast<std::string *>(ExceptionInfo->ExceptionRecord->ExceptionInformation[1]);
if (IsReadable(possibleStdStringPointer))
{
entry.wincxx.str = exception->what();
auto string = *possibleStdStringPointer;
if (suffix.size()) suffix += ", ";
suffix += string;
}
}
}
if (derivedFromException)
{
auto fatanthony = exception->what();
if (fatanthony)
{
entry.wincxx.str += AuString("\r\n ") + fatanthony;
}
}
if (suffix.size())
{
entry.wincxx.str += AuString("\r\n ") + suffix;
}
}
}
bool isCritical = AuTryFind(kExceptionFatalTable, ExceptionInfo->ExceptionRecord->ExceptionCode);

View File

@ -183,11 +183,10 @@ namespace Aurora::IO::FS
bool NtAsyncFileTransaction::StartRead(AuUInt64 offset, void *buffer, AuUInt32 length)
{
if (this->latch_)
if (std::exchange(this->latch_, {}))
{
return {};
}
this->latch_ = {};
this->lastAbstractStat_ = length;
this->lastAbstractOffset_ = offset;
this->overlap_.Offset = offset & 0xFFFFFFFF;
@ -199,11 +198,10 @@ namespace Aurora::IO::FS
bool NtAsyncFileTransaction::StartWrite(AuUInt64 offset, const void *buffer, AuUInt32 length)
{
if (this->latch_)
if (std::exchange(this->latch_, {}))
{
return {};
}
this->latch_ = {};
this->lastAbstractStat_ = length;
this->lastAbstractOffset_ = offset;
this->overlap_.Offset = offset & 0xFFFFFFFF;
@ -220,14 +218,15 @@ namespace Aurora::IO::FS
return;
}
this->pin_ = {};
if (this->sub_)
{
DWORD read {};
GetOverlappedResult(this->handle_->handle, &this->overlap_, &read, false);
this->sub_->OnAsyncFileOpFinished(this->lastAbstractOffset_, read);
}
// TODO: test for write after free
std::exchange(this->pin_, {});
}
bool NtAsyncFileTransaction::Complete()