[*] 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

@ -139,6 +139,28 @@ namespace Aurora::Async
}; };
return ret; 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>; using FVoidJob = FJob<AVoid, AVoid>;
@ -176,13 +198,13 @@ namespace Aurora::Async
return ret; return ret;
} }
template<typename Info_t = AVoid, typename Out_t = AVoid, class ClazzImpl> template<typename Info_t = AVoid, typename Out_t = AVoid>
FTask<Info_t, Out_t> TaskFromVoidVoid(AuVoidFunc &&func) FTask<Info_t, Out_t> TaskFromVoidVoid(const AuVoidFunc &func)
{ {
FTask<Info_t, Out_t> ret; FTask<Info_t, Out_t> ret;
ret.onFrame = [callable = func](const Info_t &in) -> Out_t ret.onFrame = [callable = func](const Info_t &in) -> Out_t
{ {
func(); callable();
return {}; return {};
}; };
return ret; return ret;
@ -652,12 +674,24 @@ namespace Aurora::Async
// It would be nice if we didn't have to drag the job callback pair around with us // It would be nice if we didn't have to drag the job callback pair around with us
return Async::NewWorkItem(worker, AuMakeShared<Async::BasicWorkCallback<Info_t, Result_t, Task_t>>(task, job, inputParameters), enableWait)->Dispatch(); return Async::NewWorkItem(worker, AuMakeShared<Async::BasicWorkCallback<Info_t, Result_t, Task_t>>(task, job, inputParameters), enableWait)->Dispatch();
} }
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> 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> DispatchFunctional(const WorkerId_t &worker, ClazzImpl task, const Job_t &job, const Info_t &inputParameters, bool enableWait = false) AuSPtr<Aurora::Async::IWorkItem> DispatchFunctional(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); 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_ERROR

View File

@ -105,14 +105,14 @@ namespace Aurora::Console::Commands
} }
else else
{ {
Async::DispatchBasicWorkCallback<CommandDispatch, Async::AVoid>(workerId, Async::DispatchBasicWorkCallback<CommandDispatch>(workerId,
Async::TaskFromConsumerRefT<CommandDispatch, Async::AVoid>([](const CommandDispatch &dispatch) -> AuOptional<Async::AVoid> Async::TaskFromConsumerRefT<CommandDispatch>([](const CommandDispatch &dispatch) -> void
{ {
dispatch.callback->onCommand(dispatch.arguments); 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() void InitWin32()
{ {
static AuString kStringRawName = typeid(AuString).raw_name();
#if defined(DEBUG) || defined(STAGING) #if defined(DEBUG) || defined(STAGING)
SymInitialize(GetCurrentProcess(), NULL, TRUE); SymInitialize(GetCurrentProcess(), NULL, TRUE);
#endif #endif
@ -234,60 +237,61 @@ namespace Aurora::Debug
handle = reinterpret_cast<HMODULE>(ExceptionInfo->ExceptionRecord->ExceptionInformation[3]); handle = reinterpret_cast<HMODULE>(ExceptionInfo->ExceptionRecord->ExceptionInformation[3]);
} }
const auto catchableTypeArray = reinterpret_cast<const CatchableTypeArray*>(reinterpret_cast<AuUInt>(handle) + static_cast<AuUInt>(throwInfo->pCatchableTypeArray)); auto exception = reinterpret_cast<std::exception *>(ExceptionInfo->ExceptionRecord->ExceptionInformation[1]);
const auto type = reinterpret_cast<CatchableType*> (reinterpret_cast<AuUInt>(handle) + static_cast<AuUInt>(catchableTypeArray->arrayOfCatchableTypes[0])); const auto catchableTypeArray = reinterpret_cast<const CatchableTypeArray*>(reinterpret_cast<AuUInt>(handle) + static_cast<AuUInt>(throwInfo->pCatchableTypeArray));
const auto descriptor = reinterpret_cast<TypeDescriptor*> (reinterpret_cast<AuUInt>(handle) + static_cast<AuUInt>(type->pType));
AuString suffix;
// .?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 bool derivedFromException = {};
// 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) for (int i = 0; i < catchableTypeArray->nCatchableTypes; i++)
{ {
auto exception = reinterpret_cast<std::exception *>(ExceptionInfo->ExceptionRecord->ExceptionInformation[1]); const auto type = reinterpret_cast<CatchableType *> (reinterpret_cast<AuUInt>(handle) + static_cast<AuUInt>(catchableTypeArray->arrayOfCatchableTypes[i]));
if (IsReadable(exception)) 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)
{ {
entry.wincxx.str = exception->what(); derivedFromException = true;
} }
} else if (strncmp(descriptor->raw_name(), ".PEAD", AuArraySize(".PEAD") - 1) == 0)
else if (((type->properties & CT_IsSimpleType) != 0) &&
((type->properties & CT_IsWinRTHandle) == 0))
{
// assert descriptor->name == ".PEAD"? `DEAP.`?
auto possibleStringPointer = reinterpret_cast<const char **>(ExceptionInfo->ExceptionRecord->ExceptionInformation[1]);
if (IsReadable(possibleStringPointer))
{ {
auto string = *possibleStringPointer; auto possibleStringPointer = reinterpret_cast<const char **>(ExceptionInfo->ExceptionRecord->ExceptionInformation[1]);
// Not a string? I don't care, it has a null byte under 1k in a readable page if (IsReadable(possibleStringPointer))
if (IsReadable(string) && (strnlen(string, 4096) < 1024))
{ {
entry.wincxx.str = string; auto string = *possibleStringPointer;
if (IsReadable(string) && (strnlen(string, 4096) < 1024))
{
if (suffix.size()) suffix += ", ";
suffix += string;
}
}
}
else if (strncmp(descriptor->raw_name(), kStringRawName.data(), kStringRawName.size()) == 0)
{
auto possibleStdStringPointer = reinterpret_cast<std::string *>(ExceptionInfo->ExceptionRecord->ExceptionInformation[1]);
if (IsReadable(possibleStdStringPointer))
{
auto string = *possibleStdStringPointer;
if (suffix.size()) suffix += ", ";
suffix += string;
} }
} }
} }
//else if (strnicmp(descriptor->name, ".?AV", AuArraySize(".?AV") - 1) == 0)
//{ if (derivedFromException)
// /* 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)
{ {
auto exception = reinterpret_cast<std::exception *>(ExceptionInfo->ExceptionRecord->ExceptionInformation[1]); auto fatanthony = exception->what();
if (IsReadable(exception)) if (fatanthony)
{ {
entry.wincxx.str = exception->what(); entry.wincxx.str += AuString("\r\n ") + fatanthony;
} }
} }
if (suffix.size())
{
entry.wincxx.str += AuString("\r\n ") + suffix;
}
} }
} }

View File

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