[*] 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:
parent
a679ecb534
commit
3d859a319e
@ -139,6 +139,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>;
|
||||
|
||||
@ -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;
|
||||
@ -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
|
||||
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>
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -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
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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,60 +237,61 @@ 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]);
|
||||
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++)
|
||||
{
|
||||
auto exception = reinterpret_cast<std::exception *>(ExceptionInfo->ExceptionRecord->ExceptionInformation[1]);
|
||||
if (IsReadable(exception))
|
||||
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)
|
||||
{
|
||||
entry.wincxx.str = exception->what();
|
||||
derivedFromException = true;
|
||||
}
|
||||
}
|
||||
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))
|
||||
else if (strncmp(descriptor->raw_name(), ".PEAD", AuArraySize(".PEAD") - 1) == 0)
|
||||
{
|
||||
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))
|
||||
auto possibleStringPointer = reinterpret_cast<const char **>(ExceptionInfo->ExceptionRecord->ExceptionInformation[1]);
|
||||
if (IsReadable(possibleStringPointer))
|
||||
{
|
||||
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)
|
||||
//{
|
||||
// /* 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)
|
||||
|
||||
if (derivedFromException)
|
||||
{
|
||||
auto exception = reinterpret_cast<std::exception *>(ExceptionInfo->ExceptionRecord->ExceptionInformation[1]);
|
||||
if (IsReadable(exception))
|
||||
auto fatanthony = exception->what();
|
||||
if (fatanthony)
|
||||
{
|
||||
entry.wincxx.str = exception->what();
|
||||
entry.wincxx.str += AuString("\r\n ") + fatanthony;
|
||||
}
|
||||
}
|
||||
|
||||
if (suffix.size())
|
||||
{
|
||||
entry.wincxx.str += AuString("\r\n ") + suffix;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
@ -219,8 +217,6 @@ namespace Aurora::IO::FS
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this->pin_ = {};
|
||||
|
||||
if (this->sub_)
|
||||
{
|
||||
@ -228,6 +224,9 @@ namespace Aurora::IO::FS
|
||||
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()
|
||||
|
Loading…
Reference in New Issue
Block a user