From 37acfa64f05e103963dae0174d1af9175f0d2cd9 Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Thu, 28 Nov 2019 09:57:04 -0800 Subject: [PATCH] Fixed windows race condition between garbage collecting spawned process and exit handler, if the memory was reclaimed at just the right time --- microscript/ILibDuktape_ChildProcess.c | 4 +++- microstack/ILibProcessPipe.c | 14 +++++++++++++- microstack/ILibProcessPipe.h | 1 + 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/microscript/ILibDuktape_ChildProcess.c b/microscript/ILibDuktape_ChildProcess.c index 9e56b98..41e331a 100644 --- a/microscript/ILibDuktape_ChildProcess.c +++ b/microscript/ILibDuktape_ChildProcess.c @@ -102,7 +102,6 @@ void ILibDuktape_ChildProcess_SubProcess_ExitHandler(ILibProcessPipe_Process sen p->exitCode = exitCode; p->childProcess = NULL; - duk_push_heapptr(p->ctx, p->subProcess); // [childProcess] #ifdef WIN32 @@ -194,6 +193,9 @@ duk_ret_t ILibDuktape_ChildProcess_waitExit(duk_context *ctx) } duk_ret_t ILibDuktape_ChildProcess_SpawnedProcess_Finalizer(duk_context *ctx) { + ILibDuktape_ChildProcess_SubProcess *retVal = (ILibDuktape_ChildProcess_SubProcess*)Duktape_GetBufferProperty(ctx, 0, ILibDuktape_ChildProcess_MemBuf); + ILibProcessPipe_Process_RemoveHandlers(retVal->childProcess); + duk_get_prop_string(ctx, 0, "kill"); // [kill] duk_dup(ctx, 0); // [kill][this] duk_call_method(ctx, 0); diff --git a/microstack/ILibProcessPipe.c b/microstack/ILibProcessPipe.c index 8a53624..5211638 100644 --- a/microstack/ILibProcessPipe.c +++ b/microstack/ILibProcessPipe.c @@ -112,6 +112,7 @@ typedef struct ILibProcessPipe_Process_Object #ifdef WIN32 HANDLE hProcess; int hProcess_needAdd; + int disabled; #endif void *chain; }ILibProcessPipe_Process_Object; @@ -1442,7 +1443,7 @@ void ILibProcessPipe_Pipe_Resume(ILibProcessPipe_Pipe pipeObject) else { ILibProcessPipe_Pipe_ResumeEx(p); - if (p->mProcess != NULL && p->mProcess->hProcess_needAdd != 0) + if (p->mProcess != NULL && p->mProcess->hProcess_needAdd != 0 && p->mProcess->disabled == 0) { p->mProcess->hProcess_needAdd = 0; ILibProcessPipe_WaitHandle_Add(p->manager, p->mProcess->hProcess, p->mProcess, ILibProcessPipe_Process_OnExit); @@ -1567,6 +1568,7 @@ void ILibProcessPipe_Process_OnExit_ChainSink(void *chain, void *user) ILibProcessPipe_Process_Object* j = (ILibProcessPipe_Process_Object*)user; DWORD exitCode; BOOL result; + if (j->disabled != 0) { return; } if (ILibChain_SelectInterrupted(j->chain) != 0) { @@ -1598,6 +1600,7 @@ BOOL ILibProcessPipe_Process_OnExit(HANDLE event, ILibWaitHandle_ErrorStatus err UNREFERENCED_PARAMETER(event); ILibProcessPipe_WaitHandle_Remove(j->parent, j->hProcess); + if ((j->stdOut->PAUSED != 0 && j->stdOut->totalRead > 0) || (j->stdErr->PAUSED != 0 && j->stdErr->totalRead > 0)) { j->hProcess_needAdd = 1; @@ -1625,6 +1628,15 @@ void ILibProcessPipe_Process_UpdateUserObject(ILibProcessPipe_Process module, vo { ((ILibProcessPipe_Process_Object*)module)->userObject = userObj; } +void ILibProcessPipe_Process_RemoveHandlers(ILibProcessPipe_Process module) +{ + ILibProcessPipe_Process_Object* j = (ILibProcessPipe_Process_Object*)module; + if (j != NULL && ILibMemory_CanaryOK(j)) + { + j->disabled = 1; + ILibProcessPipe_WaitHandle_Remove(j->parent, j->hProcess); + } +} void ILibProcessPipe_Process_AddHandlers(ILibProcessPipe_Process module, int bufferSize, ILibProcessPipe_Process_ExitHandler exitHandler, ILibProcessPipe_Process_OutputHandler stdOut, ILibProcessPipe_Process_OutputHandler stdErr, ILibProcessPipe_Process_SendOKHandler sendOk, void *user) { ILibProcessPipe_Process_Object* j = (ILibProcessPipe_Process_Object*)module; diff --git a/microstack/ILibProcessPipe.h b/microstack/ILibProcessPipe.h index fd23d6a..6ae6846 100644 --- a/microstack/ILibProcessPipe.h +++ b/microstack/ILibProcessPipe.h @@ -80,6 +80,7 @@ ILibProcessPipe_Process ILibProcessPipe_Manager_SpawnProcessEx4(ILibProcessPipe_ #define ILibProcessPipe_Manager_SpawnProcessWithExtraPipeMemory(pipeManager, target, parameters, memorySize) ILibProcessPipe_Manager_SpawnProcessEx2(pipeManager, target, parameters, ILibProcessPipe_SpawnTypes_DEFAULT, memorySize) void ILibProcessPipe_Process_SoftKill(ILibProcessPipe_Process p); void ILibProcessPipe_Process_AddHandlers(ILibProcessPipe_Process module, int bufferSize, ILibProcessPipe_Process_ExitHandler exitHandler, ILibProcessPipe_Process_OutputHandler stdOut, ILibProcessPipe_Process_OutputHandler stdErr, ILibProcessPipe_Process_SendOKHandler sendOk, void *user); +void ILibProcessPipe_Process_RemoveHandlers(ILibProcessPipe_Process module); void ILibProcessPipe_Process_UpdateUserObject(ILibProcessPipe_Process module, void *userObj); ILibTransport_DoneState ILibProcessPipe_Process_WriteStdIn(ILibProcessPipe_Process p, char* buffer, int bufferLen, ILibTransport_MemoryOwnership ownership); void ILibProcessPipe_Process_CloseStdIn(ILibProcessPipe_Process p);