diff --git a/microscript/ILibDuktape_ReadableStream.c b/microscript/ILibDuktape_ReadableStream.c index b96e69f..032f08e 100644 --- a/microscript/ILibDuktape_ReadableStream.c +++ b/microscript/ILibDuktape_ReadableStream.c @@ -276,7 +276,18 @@ void __stdcall ILibDuktape_readableStream_WriteData_OnData_ChainThread_APC(ULONG { 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); + + if (ILibChain_SelectInterrupted(chain) != 0) + { + // This APC interrupted a winsock (select) call, so we must unroll the callstack to continue, + // because winsock is not re-entrant, so we cannot risk making another winsock call directly. + // + ILibChain_RunOnMicrostackThreadEx2(chain, ILibDuktape_readableStream_WriteData_OnData_ChainThread, (void*)obj, 0); + } + else + { + ILibDuktape_readableStream_WriteData_OnData_ChainThread(chain, (void*)obj); + } } #endif diff --git a/microstack/ILibParsers.c b/microstack/ILibParsers.c index bba5046..4eecc21 100644 --- a/microstack/ILibParsers.c +++ b/microstack/ILibParsers.c @@ -1510,6 +1510,10 @@ HANDLE ILibChain_GetMicrostackThreadHandle(void *chain) { return(((struct ILibBaseChain*)chain)->MicrostackThreadHandle); } +int ILibChain_SelectInterrupted(void *chain) +{ + return(((struct ILibBaseChain*)chain)->PreSelectCount == 0 ? 0 : !(((struct ILibBaseChain*)chain)->PreSelectCount == ((struct ILibBaseChain*)chain)->PostSelectCount && ((struct ILibBaseChain*)chain)->PreSelectCount != 0)); +} #endif void ILibChain_Safe_Destroy(void *object) diff --git a/microstack/ILibParsers.h b/microstack/ILibParsers.h index 09f5f8d..007a8ab 100644 --- a/microstack/ILibParsers.h +++ b/microstack/ILibParsers.h @@ -954,6 +954,7 @@ int ILibIsRunningOnChainThread(void* chain); #define ILibChain_RunOnMicrostackThread2(chain, handler, user, freeOnShutdown) if(ILibIsRunningOnChainThread(chain)==0){ILibChain_RunOnMicrostackThreadEx2(chain, handler, user, freeOnShutdown);}else{handler(chain,user);} #ifdef WIN32 HANDLE ILibChain_GetMicrostackThreadHandle(void *chain); + int ILibChain_SelectInterrupted(void *chain); #endif /* \} */ diff --git a/microstack/ILibProcessPipe.c b/microstack/ILibProcessPipe.c index f92acf3..b072f03 100644 --- a/microstack/ILibProcessPipe.c +++ b/microstack/ILibProcessPipe.c @@ -860,8 +860,8 @@ ILibProcessPipe_Process ILibProcessPipe_Manager_SpawnProcessEx4(ILibProcessPipe_ info.dwFlags |= STARTF_USESTDHANDLES; } - if ((spawnType == ILibProcessPipe_SpawnTypes_DEFAULT && !CreateProcessA(target, parms, NULL, NULL, TRUE, CREATE_NO_WINDOW, envvars, NULL, &info, &processInfo)) || - (spawnType != ILibProcessPipe_SpawnTypes_DEFAULT && !CreateProcessAsUserA(userToken, target, parms, NULL, NULL, TRUE, CREATE_NO_WINDOW, envvars, NULL, &info, &processInfo))) + if ((spawnType == ILibProcessPipe_SpawnTypes_DEFAULT && !CreateProcessA(target, parms, NULL, NULL, TRUE, CREATE_NO_WINDOW | (needSetSid !=0? (DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP) : 0x00), envvars, NULL, &info, &processInfo)) || + (spawnType != ILibProcessPipe_SpawnTypes_DEFAULT && !CreateProcessAsUserA(userToken, target, parms, NULL, NULL, TRUE, CREATE_NO_WINDOW | (needSetSid != 0 ? (DETACHED_PROCESS| CREATE_NEW_PROCESS_GROUP) : 0x00), envvars, NULL, &info, &processInfo))) { if (spawnType != ILibProcessPipe_SpawnTypes_DETACHED) { @@ -1543,6 +1543,15 @@ void ILibProcessPipe_Process_OnExit_ChainSink(void *chain, void *user) DWORD exitCode; BOOL result; + if (ILibChain_SelectInterrupted(j->chain) != 0) + { + // Winsock appears to be at a select call, so this must've been triggered by an APC, so we must unroll the callstack to continue, + // because winsock is not re-entrant, so we cannot risk making another winsock call directly. + // + ILibChain_RunOnMicrostackThreadEx2(j->chain, ILibProcessPipe_Process_OnExit_ChainSink, user, 0); + return; + } + result = GetExitCodeProcess(j->hProcess, &exitCode); j->exiting = 1; j->exitHandler(j, exitCode, j->userObject);