mirror of
https://github.com/Ylianst/MeshAgent
synced 2025-12-06 00:13:33 +00:00
1. Updated so that APCs are used for thread dispatching for Read/Exit on Windows
2. Updated to add support for child_process.waitExit() on Windows.
This commit is contained in:
@@ -99,10 +99,19 @@ void ILibDuktape_ChildProcess_SubProcess_ExitHandler(ILibProcessPipe_Process sen
|
||||
p->childProcess = NULL;
|
||||
|
||||
duk_push_heapptr(p->ctx, p->subProcess); // [childProcess]
|
||||
|
||||
#ifdef WIN32
|
||||
HANDLE exitptr = (HANDLE)Duktape_GetPointerProperty(p->ctx, -1, "\xFF_WaitExit");
|
||||
if (exitptr != NULL)
|
||||
{
|
||||
SetEvent(exitptr);
|
||||
}
|
||||
#else
|
||||
if (Duktape_GetIntPropertyValue(p->ctx, -1, "\xFF_WaitExit", 0) != 0)
|
||||
{
|
||||
ILibChain_EndContinue(Duktape_GetChain(p->ctx));
|
||||
}
|
||||
#endif
|
||||
duk_get_prop_string(p->ctx, -1, "emit"); // [childProcess][emit]
|
||||
duk_swap_top(p->ctx, -2); // [emit][this]
|
||||
duk_push_string(p->ctx, "exit"); // [emit][this][exit]
|
||||
@@ -153,16 +162,26 @@ duk_ret_t ILibDuktape_ChildProcess_waitExit(duk_context *ctx)
|
||||
}
|
||||
|
||||
duk_push_this(ctx); // [spawnedProcess]
|
||||
duk_push_int(ctx, 1); // [spawnedProcess][flag]
|
||||
duk_put_prop_string(ctx, -2, "\xFF_WaitExit"); // [spawnedProcess]
|
||||
|
||||
if (!ILibChain_IsLinkAlive(Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Manager)))
|
||||
{
|
||||
return(ILibDuktape_Error(ctx, "Cannot waitExit() because JS Engine is exiting"));
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
HANDLE eptr = CreateEventA(NULL, TRUE, FALSE, NULL);
|
||||
duk_push_pointer(ctx, (void*)eptr);
|
||||
#else
|
||||
duk_push_int(ctx, 1); // [spawnedProcess][flag]
|
||||
#endif
|
||||
duk_put_prop_string(ctx, -2, "\xFF_WaitExit"); // [spawnedProcess]
|
||||
|
||||
#ifdef WIN32
|
||||
while (WaitForSingleObjectEx(eptr, INFINITE, TRUE) != WAIT_OBJECT_0);
|
||||
CloseHandle(eptr);
|
||||
#else
|
||||
void *mods[] = { ILibGetBaseTimer(Duktape_GetChain(ctx)), Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Manager) };
|
||||
ILibChain_Continue(chain, (ILibChain_Link**)mods, 2, -1);
|
||||
#endif
|
||||
|
||||
return(0);
|
||||
}
|
||||
@@ -195,10 +214,7 @@ ILibDuktape_ChildProcess_SubProcess* ILibDuktape_ChildProcess_SpawnedProcess_PUS
|
||||
ILibDuktape_EventEmitter_CreateEventEx(emitter, "error");
|
||||
ILibDuktape_EventEmitter_PrependOnce(ctx, -1, "~", ILibDuktape_ChildProcess_SpawnedProcess_Finalizer);
|
||||
ILibDuktape_CreateInstanceMethod(ctx, "kill", ILibDuktape_ChildProcess_Kill, 0);
|
||||
|
||||
#ifndef WIN32
|
||||
ILibDuktape_CreateInstanceMethod(ctx, "waitExit", ILibDuktape_ChildProcess_waitExit, 0);
|
||||
#endif
|
||||
|
||||
if (ILibProcessPipe_Process_IsDetached(mProcess) == 0)
|
||||
{
|
||||
|
||||
@@ -271,6 +271,14 @@ void ILibDuktape_readableStream_WriteDataEx_Chain(void *chain, void *user)
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
#ifdef WIN32
|
||||
void __stdcall ILibDuktape_readableStream_WriteData_OnData_ChainThread_APC(ULONG_PTR obj)
|
||||
{
|
||||
ILibDuktape_readableStream_bufferedData *data = (ILibDuktape_readableStream_bufferedData*)obj;
|
||||
void *chain = ((void**)ILibMemory_GetExtraMemory((void*)obj, sizeof(ILibDuktape_readableStream_bufferedData) + data->bufferLen))[0];
|
||||
ILibDuktape_readableStream_WriteData_OnData_ChainThread(chain, (void*)obj);
|
||||
}
|
||||
#endif
|
||||
|
||||
int ILibDuktape_readableStream_WriteDataEx(ILibDuktape_readableStream *stream, int streamReserved, char* buffer, int bufferLen)
|
||||
{
|
||||
@@ -399,13 +407,25 @@ int ILibDuktape_readableStream_WriteDataEx(ILibDuktape_readableStream *stream, i
|
||||
else
|
||||
{
|
||||
// Need to PAUSE, and context switch to Chain Thread, so we can dispatch into JavaScript
|
||||
#ifdef WIN32
|
||||
ILibDuktape_readableStream_bufferedData *tmp = (ILibDuktape_readableStream_bufferedData*)ILibMemory_Allocate(sizeof(ILibDuktape_readableStream_bufferedData) + bufferLen, sizeof(void*), NULL, NULL);
|
||||
#else
|
||||
ILibDuktape_readableStream_bufferedData *tmp = (ILibDuktape_readableStream_bufferedData*)ILibMemory_Allocate(sizeof(ILibDuktape_readableStream_bufferedData) + bufferLen, 0, NULL, NULL);
|
||||
#endif
|
||||
tmp->bufferLen = bufferLen;
|
||||
tmp->Reserved = streamReserved;
|
||||
tmp->Next = (ILibDuktape_readableStream_bufferedData*)stream;
|
||||
memcpy_s(tmp->buffer, bufferLen, buffer, bufferLen);
|
||||
needPause = 1;
|
||||
#ifdef WIN32
|
||||
// We are going to PAUSE first, do the APC, then exit, to prevent a race condition. We don't want to PAUSE after the APC completes.
|
||||
if (stream->paused == 0 && stream->PauseHandler != NULL) { stream->paused = 1; stream->PauseHandler(stream, stream->user); }
|
||||
((void**)ILibMemory_GetExtraMemory(tmp, sizeof(ILibDuktape_readableStream_bufferedData) + bufferLen))[0] = stream->chain;
|
||||
QueueUserAPC((PAPCFUNC)ILibDuktape_readableStream_WriteData_OnData_ChainThread_APC, ILibChain_GetMicrostackThreadHandle(stream->chain), (ULONG_PTR)tmp);
|
||||
return(stream->paused);
|
||||
#else
|
||||
ILibChain_RunOnMicrostackThread(stream->chain, ILibDuktape_readableStream_WriteData_OnData_ChainThread, tmp);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if (stream->PauseHandler != NULL && ILibDuktape_EventEmitter_HasListeners(stream->emitter, "end") == 0)
|
||||
|
||||
@@ -1551,6 +1551,12 @@ void ILibProcessPipe_Process_OnExit_ChainSink(void *chain, void *user)
|
||||
// We can't destroy this now, because we're on the MicrostackThread. We must destroy this on the WindowsRunLoop Thread.
|
||||
QueueUserAPC((PAPCFUNC)ILibProcessPipe_Process_OnExit_ChainSink_DestroySink, j->parent->workerThread, (ULONG_PTR)j);
|
||||
}
|
||||
#ifdef WIN32
|
||||
void __stdcall ILibProcessPipe_Process_OnExit_ChainSink_APC(ULONG_PTR obj)
|
||||
{
|
||||
ILibProcessPipe_Process_OnExit_ChainSink(NULL, (void*)obj);
|
||||
}
|
||||
#endif
|
||||
BOOL ILibProcessPipe_Process_OnExit(HANDLE event, ILibWaitHandle_ErrorStatus errors, void* user)
|
||||
{
|
||||
ILibProcessPipe_Process_Object* j = (ILibProcessPipe_Process_Object*)user;
|
||||
@@ -1566,8 +1572,12 @@ BOOL ILibProcessPipe_Process_OnExit(HANDLE event, ILibWaitHandle_ErrorStatus err
|
||||
{
|
||||
if (j->exitHandler != NULL)
|
||||
{
|
||||
// Everyone's lifes is made easier, by context switching to chain thread before making this call
|
||||
// Everyone's lives will be made easier, by context switching to chain thread before making this call
|
||||
#ifdef WIN32
|
||||
QueueUserAPC((PAPCFUNC)ILibProcessPipe_Process_OnExit_ChainSink_APC, ILibChain_GetMicrostackThreadHandle(j->parent->ChainLink.ParentChain), (ULONG_PTR)user);
|
||||
#else
|
||||
ILibChain_RunOnMicrostackThread(j->parent->ChainLink.ParentChain, ILibProcessPipe_Process_OnExit_ChainSink, user);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user