mirror of
https://github.com/Ylianst/MeshAgent
synced 2025-12-14 15:23:39 +00:00
1. Updated WaitHandle_Add2 to no use APC to dispatch to event loop, becuase winsock is not re-entrant, and don't want to risk corruption
2. Updated memory handling for async methods in Generic Marshal
This commit is contained in:
@@ -47,6 +47,8 @@ limitations under the License.
|
|||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define ILibDuktape_GenericMarshal_INVALID_PROMISE ((void*)(uintptr_t)0x01)
|
||||||
|
|
||||||
#define ILibDuktape_GenericMarshal_FuncHandler "\xFF_GenericMarshal_FuncHandler"
|
#define ILibDuktape_GenericMarshal_FuncHandler "\xFF_GenericMarshal_FuncHandler"
|
||||||
#define ILibDuktape_GenericMarshal_VariableType "\xFF_GenericMarshal_VarType"
|
#define ILibDuktape_GenericMarshal_VariableType "\xFF_GenericMarshal_VarType"
|
||||||
#define ILibDuktape_GenericMarshal_GlobalSet_List "\xFF_GenericMarshal_GlobalSet_List"
|
#define ILibDuktape_GenericMarshal_GlobalSet_List "\xFF_GenericMarshal_GlobalSet_List"
|
||||||
@@ -975,20 +977,23 @@ duk_ret_t ILibDuktape_GenericMarshal_MethodInvokeAsync_abort(duk_context *ctx)
|
|||||||
{
|
{
|
||||||
if (data->waitingForResult == 0)
|
if (data->waitingForResult == 0)
|
||||||
{
|
{
|
||||||
// We cannot gracefully exit the thread, so let's reject the promise, and let the app layer figure it out
|
if (data->promise != ILibDuktape_GenericMarshal_INVALID_PROMISE)
|
||||||
duk_push_heapptr(data->ctx, data->promise); // [promise]
|
{
|
||||||
duk_get_prop_string(data->ctx, -1, "_REJ"); // [promise][rej]
|
// We cannot gracefully exit the thread, so let's reject the promise, and let the app layer figure it out
|
||||||
duk_swap_top(data->ctx, -2); // [rej][this]
|
duk_push_heapptr(data->ctx, data->promise); // [promise]
|
||||||
duk_push_string(data->ctx, "ABORT"); // [rej][this][abort]
|
duk_get_prop_string(data->ctx, -1, "_REJ"); // [promise][rej]
|
||||||
|
duk_swap_top(data->ctx, -2); // [rej][this]
|
||||||
|
duk_push_string(data->ctx, "ABORT"); // [rej][this][abort]
|
||||||
|
|
||||||
data->abort = 1;
|
data->abort = 1;
|
||||||
duk_call_method(ctx, 1);
|
duk_call_method(ctx, 1);
|
||||||
duk_pop(ctx); // ...
|
duk_pop(ctx); // ...
|
||||||
|
|
||||||
//
|
//
|
||||||
// We are purposefully not clearing the promise, becuase the hope is that the above layer
|
// We are purposefully not clearing the promise, becuase the hope is that the above layer
|
||||||
// will receive this rejection, and do a proper cleanup, which may need the promise to accomplish that.
|
// will receive this rejection, and do a proper cleanup, which may need the promise to accomplish that.
|
||||||
//
|
//
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1027,11 +1032,15 @@ duk_ret_t ILibDuktape_GenericMarshal_MethodInvokeAsync_dataFinalizer(duk_context
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
void __stdcall ILibDuktape_GenericMarshal_MethodInvokeAsync_Done_APC(ULONG_PTR u)
|
void ILibDuktape_GenericMarshal_MethodInvokeAsync_Done_chain(void *chain, void* u)
|
||||||
{
|
{
|
||||||
ILibDuktape_FFI_AsyncData *data = (ILibDuktape_FFI_AsyncData*)u;
|
ILibDuktape_FFI_AsyncData *data = (ILibDuktape_FFI_AsyncData*)u;
|
||||||
duk_context *ctx;
|
duk_context *ctx;
|
||||||
if (!ILibMemory_CanaryOK(data)) { return; }
|
if (!ILibMemory_CanaryOK(data)) { return; }
|
||||||
|
if (!ILibMemory_CanaryOK(data->ctx) || data->promise == NULL || data->promise == ILibDuktape_GenericMarshal_INVALID_PROMISE)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
duk_push_heapptr(data->ctx, data->promise); // [promise]
|
duk_push_heapptr(data->ctx, data->promise); // [promise]
|
||||||
duk_get_prop_string(data->ctx, -1, "_RES"); // [promise][resolver]
|
duk_get_prop_string(data->ctx, -1, "_RES"); // [promise][resolver]
|
||||||
@@ -1062,10 +1071,20 @@ void __stdcall ILibDuktape_GenericMarshal_MethodInvokeAsync_APC(ULONG_PTR u)
|
|||||||
data->workAvailable = (void*)ILibDuktape_GenericMarshal_MethodInvoke_Native(varCount-1, data->fptr, var);
|
data->workAvailable = (void*)ILibDuktape_GenericMarshal_MethodInvoke_Native(varCount-1, data->fptr, var);
|
||||||
data->lastError = (DWORD)GetLastError();
|
data->lastError = (DWORD)GetLastError();
|
||||||
|
|
||||||
QueueUserAPC((PAPCFUNC)ILibDuktape_GenericMarshal_MethodInvokeAsync_Done_APC, data->workFinished, (ULONG_PTR)data);
|
ILibChain_RunOnMicrostackThread(data->chain, ILibDuktape_GenericMarshal_MethodInvokeAsync_Done_chain, data);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
duk_ret_t ILibDuktape_GenericMarshal_MethodInvokeAsync_promfin(duk_context *ctx)
|
||||||
|
{
|
||||||
|
ILibDuktape_FFI_AsyncData *data = (ILibDuktape_FFI_AsyncData*)Duktape_GetPointerProperty(ctx, 0, "_data");
|
||||||
|
void *h = duk_get_heapptr(ctx, 0);
|
||||||
|
|
||||||
|
if (ILibMemory_CanaryOK(data) && data->promise == h)
|
||||||
|
{
|
||||||
|
data->promise = ILibDuktape_GenericMarshal_INVALID_PROMISE;
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
duk_ret_t ILibDuktape_GenericMarshal_MethodInvokeAsync(duk_context *ctx)
|
duk_ret_t ILibDuktape_GenericMarshal_MethodInvokeAsync(duk_context *ctx)
|
||||||
{
|
{
|
||||||
void *redirectionPtr = NULL, *redirectionPtrName = NULL;
|
void *redirectionPtr = NULL, *redirectionPtrName = NULL;
|
||||||
@@ -1095,17 +1114,21 @@ duk_ret_t ILibDuktape_GenericMarshal_MethodInvokeAsync(duk_context *ctx)
|
|||||||
Duktape_GlobalGeneric_Data *ggd = (Duktape_GlobalGeneric_Data*)Duktape_GetPointerProperty(ctx, 0, ILibDuktape_GenericMarshal_GlobalSet_Dispatcher);
|
Duktape_GlobalGeneric_Data *ggd = (Duktape_GlobalGeneric_Data*)Duktape_GetPointerProperty(ctx, 0, ILibDuktape_GenericMarshal_GlobalSet_Dispatcher);
|
||||||
redirectionPtr = NULL;
|
redirectionPtr = NULL;
|
||||||
|
|
||||||
duk_eval_string(ctx, "require('promise');"); // [func][promise]
|
|
||||||
duk_push_c_function(ctx, ILibDuktape_GenericMarshal_MethodInvokeAsync_promise, 2);
|
|
||||||
duk_new(ctx, 1);
|
|
||||||
ggd->dispatch->promise = duk_get_heapptr(ctx, -1);
|
|
||||||
data = (ILibDuktape_FFI_AsyncData*)ILibMemory_SmartAllocate(sizeof(ILibDuktape_FFI_AsyncData));
|
data = (ILibDuktape_FFI_AsyncData*)ILibMemory_SmartAllocate(sizeof(ILibDuktape_FFI_AsyncData));
|
||||||
duk_push_pointer(ctx, data);
|
duk_push_pointer(ctx, data);
|
||||||
duk_put_prop_string(ctx, -2, ILibDuktape_FFI_AsyncDataPtr);
|
duk_put_prop_string(ctx, -2, ILibDuktape_FFI_AsyncDataPtr);
|
||||||
|
|
||||||
|
duk_eval_string(ctx, "require('promise');"); // [func][promise]
|
||||||
|
duk_push_c_function(ctx, ILibDuktape_GenericMarshal_MethodInvokeAsync_promise, 2);
|
||||||
|
duk_new(ctx, 1);
|
||||||
|
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_GenericMarshal_MethodInvokeAsync_promfin);
|
||||||
|
duk_push_pointer(ctx, data); duk_put_prop_string(ctx, -2, "_data");
|
||||||
|
ggd->dispatch->promise = duk_get_heapptr(ctx, -1);
|
||||||
|
|
||||||
data->ctx = ctx;
|
data->ctx = ctx;
|
||||||
data->ctxnonce = duk_ctx_nonce(ctx);
|
data->ctxnonce = duk_ctx_nonce(ctx);
|
||||||
data->promise = ggd->dispatch->promise;
|
data->promise = ggd->dispatch->promise;
|
||||||
|
data->chain = duk_ctx_chain(ctx);
|
||||||
|
|
||||||
duk_push_current_function(ctx); // [promise][func]
|
duk_push_current_function(ctx); // [promise][func]
|
||||||
data->fptr = Duktape_GetPointerProperty(ctx, -1, "_address");
|
data->fptr = Duktape_GetPointerProperty(ctx, -1, "_address");
|
||||||
@@ -1157,6 +1180,8 @@ duk_ret_t ILibDuktape_GenericMarshal_MethodInvokeAsync(duk_context *ctx)
|
|||||||
duk_eval_string(ctx, "require('promise');"); // [func][promise]
|
duk_eval_string(ctx, "require('promise');"); // [func][promise]
|
||||||
duk_push_c_function(ctx, ILibDuktape_GenericMarshal_MethodInvokeAsync_promise, 2);
|
duk_push_c_function(ctx, ILibDuktape_GenericMarshal_MethodInvokeAsync_promise, 2);
|
||||||
duk_new(ctx, 1);
|
duk_new(ctx, 1);
|
||||||
|
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_GenericMarshal_MethodInvokeAsync_promfin);
|
||||||
|
duk_push_pointer(ctx, data); duk_put_prop_string(ctx, -2, "_data");
|
||||||
data->promise = duk_get_heapptr(ctx, -1);
|
data->promise = duk_get_heapptr(ctx, -1);
|
||||||
}
|
}
|
||||||
data->vars = (PTRSIZE*)ILibMemory_AllocateA(sizeof(PTRSIZE)*parms);
|
data->vars = (PTRSIZE*)ILibMemory_AllocateA(sizeof(PTRSIZE)*parms);
|
||||||
|
|||||||
@@ -181,6 +181,7 @@ typedef struct ILibProcessPipe_WaitHandle_APC
|
|||||||
HANDLE ev;
|
HANDLE ev;
|
||||||
ILibWaitHandle_ErrorStatus status;
|
ILibWaitHandle_ErrorStatus status;
|
||||||
ILibProcessPipe_WaitHandle_Handler callback;
|
ILibProcessPipe_WaitHandle_Handler callback;
|
||||||
|
void *chain;
|
||||||
void *user;
|
void *user;
|
||||||
}ILibProcessPipe_WaitHandle_APC;
|
}ILibProcessPipe_WaitHandle_APC;
|
||||||
HANDLE ILibProcessPipe_Manager_GetWorkerThread(ILibProcessPipe_Manager mgr)
|
HANDLE ILibProcessPipe_Manager_GetWorkerThread(ILibProcessPipe_Manager mgr)
|
||||||
@@ -204,6 +205,7 @@ void __stdcall ILibProcessPipe_WaitHandle_Remove_APC(ULONG_PTR obj)
|
|||||||
if (node != NULL)
|
if (node != NULL)
|
||||||
{
|
{
|
||||||
waiter = (ILibProcessPipe_WaitHandle*)ILibLinkedList_GetDataFromNode(node);
|
waiter = (ILibProcessPipe_WaitHandle*)ILibLinkedList_GetDataFromNode(node);
|
||||||
|
if (waiter->callback != NULL) { waiter->callback(waiter->event, ILibWaitHandle_ErrorStatus_REMOVED, waiter->user); }
|
||||||
free(waiter);
|
free(waiter);
|
||||||
ILibLinkedList_Remove(node);
|
ILibLinkedList_Remove(node);
|
||||||
SetEvent(manager->updateEvent);
|
SetEvent(manager->updateEvent);
|
||||||
@@ -256,7 +258,7 @@ void ILibProcessPipe_WaitHandle_Add_WithNonZeroTimeout(ILibProcessPipe_Manager m
|
|||||||
ILibProcessPipe_WaitHandle_AddEx(mgr, waitHandle);
|
ILibProcessPipe_WaitHandle_AddEx(mgr, waitHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __stdcall ILibProcessPipe_WaitHandle_Add2_apcsink(ULONG_PTR obj)
|
void ILibProcessPipe_WaitHandle_Add2_chainsink(void *chain, void *obj)
|
||||||
{
|
{
|
||||||
if (ILibMemory_CanaryOK((void*)obj))
|
if (ILibMemory_CanaryOK((void*)obj))
|
||||||
{
|
{
|
||||||
@@ -269,7 +271,14 @@ BOOL ILibProcessPipe_WaitHandle_Add2_sink(HANDLE event, ILibWaitHandle_ErrorStat
|
|||||||
{
|
{
|
||||||
if (ILibMemory_CanaryOK(user))
|
if (ILibMemory_CanaryOK(user))
|
||||||
{
|
{
|
||||||
QueueUserAPC((PAPCFUNC)ILibProcessPipe_WaitHandle_Add2_apcsink, ((ILibProcessPipe_WaitHandle_APC*)user)->callingThread, (ULONG_PTR)user);
|
if (status == ILibWaitHandle_ErrorStatus_REMOVED || ILibWaitHandle_ErrorStatus_MANAGER_EXITING)
|
||||||
|
{
|
||||||
|
ILibMemory_Free(user);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ILibChain_RunOnMicrostackThread(((ILibProcessPipe_WaitHandle_APC*)user)->chain, ILibProcessPipe_WaitHandle_Add2_chainsink, user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return(FALSE);
|
return(FALSE);
|
||||||
}
|
}
|
||||||
@@ -279,9 +288,9 @@ void ILibProcessPipe_WaitHandle_Add2_WithNonZeroTimeout(ILibProcessPipe_Manager
|
|||||||
DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &apcState->callingThread, THREAD_SET_CONTEXT, FALSE, 0);
|
DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &apcState->callingThread, THREAD_SET_CONTEXT, FALSE, 0);
|
||||||
apcState->callback = callback;
|
apcState->callback = callback;
|
||||||
apcState->user = user;
|
apcState->user = user;
|
||||||
|
apcState->chain = ((ILibProcessPipe_Manager_Object*)mgr)->ChainLink.ParentChain;
|
||||||
ILibProcessPipe_WaitHandle_Add_WithNonZeroTimeout(mgr, event, milliseconds, apcState, ILibProcessPipe_WaitHandle_Add2_sink);
|
ILibProcessPipe_WaitHandle_Add_WithNonZeroTimeout(mgr, event, milliseconds, apcState, ILibProcessPipe_WaitHandle_Add2_sink);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILibProcessPipe_Manager_WindowsRunLoopEx(void *arg)
|
void ILibProcessPipe_Manager_WindowsRunLoopEx(void *arg)
|
||||||
{
|
{
|
||||||
ILibProcessPipe_Manager_Object *manager = (ILibProcessPipe_Manager_Object*)arg;
|
ILibProcessPipe_Manager_Object *manager = (ILibProcessPipe_Manager_Object*)arg;
|
||||||
|
|||||||
@@ -106,7 +106,9 @@ typedef enum ILibWaitHandle_ErrorStatus
|
|||||||
{
|
{
|
||||||
ILibWaitHandle_ErrorStatus_NONE = 0,
|
ILibWaitHandle_ErrorStatus_NONE = 0,
|
||||||
ILibWaitHandle_ErrorStatus_INVALID_HANDLE = 1,
|
ILibWaitHandle_ErrorStatus_INVALID_HANDLE = 1,
|
||||||
ILibWaitHandle_ErrorStatus_TIMEOUT = 2
|
ILibWaitHandle_ErrorStatus_TIMEOUT = 2,
|
||||||
|
ILibWaitHandle_ErrorStatus_REMOVED = 3,
|
||||||
|
ILibWaitHandle_ErrorStatus_MANAGER_EXITING = 4
|
||||||
}ILibWaitHandle_ErrorStatus;
|
}ILibWaitHandle_ErrorStatus;
|
||||||
|
|
||||||
typedef BOOL(*ILibProcessPipe_WaitHandle_Handler)(HANDLE event, ILibWaitHandle_ErrorStatus status, void* user);
|
typedef BOOL(*ILibProcessPipe_WaitHandle_Handler)(HANDLE event, ILibWaitHandle_ErrorStatus status, void* user);
|
||||||
@@ -116,7 +118,7 @@ void ILibProcessPipe_WaitHandle_Remove(ILibProcessPipe_Manager mgr, HANDLE event
|
|||||||
void ILibProcessPipe_WaitHandle_Add_WithNonZeroTimeout(ILibProcessPipe_Manager mgr, HANDLE event, int milliseconds, void *user, ILibProcessPipe_WaitHandle_Handler callback);
|
void ILibProcessPipe_WaitHandle_Add_WithNonZeroTimeout(ILibProcessPipe_Manager mgr, HANDLE event, int milliseconds, void *user, ILibProcessPipe_WaitHandle_Handler callback);
|
||||||
#define ILibProcessPipe_WaitHandle_Add(processPipeManager, eventHandle, user, callback) ILibProcessPipe_WaitHandle_Add_WithNonZeroTimeout(processPipeManager, eventHandle, 0, user, callback)
|
#define ILibProcessPipe_WaitHandle_Add(processPipeManager, eventHandle, user, callback) ILibProcessPipe_WaitHandle_Add_WithNonZeroTimeout(processPipeManager, eventHandle, 0, user, callback)
|
||||||
|
|
||||||
// These methods will use an APC to context switch to the calling thread when dispatching
|
// These methods will context switch to the chain thread when dispatching
|
||||||
void ILibProcessPipe_WaitHandle_Add2_WithNonZeroTimeout(ILibProcessPipe_Manager mgr, HANDLE event, int milliseconds, void *user, ILibProcessPipe_WaitHandle_Handler callback);
|
void ILibProcessPipe_WaitHandle_Add2_WithNonZeroTimeout(ILibProcessPipe_Manager mgr, HANDLE event, int milliseconds, void *user, ILibProcessPipe_WaitHandle_Handler callback);
|
||||||
#define ILibProcessPipe_WaitHandle_Add2(processPipeManager, eventHandle, user, callback) ILibProcessPipe_WaitHandle_Add2_WithNonZeroTimeout(processPipeManager, eventHandle, 0, user, callback)
|
#define ILibProcessPipe_WaitHandle_Add2(processPipeManager, eventHandle, user, callback) ILibProcessPipe_WaitHandle_Add2_WithNonZeroTimeout(processPipeManager, eventHandle, 0, user, callback)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user