mirror of
https://github.com/Ylianst/MeshAgent
synced 2025-12-10 05:13:38 +00:00
1. Added ability to query if Select was interrupted with APC
2. Updated So that before readableStream and 'exit' are dispatched, APC's are unrolled if 'select' was interrupted, preventing stack corruption caused by trying to make a re-entrant winsock call, which is not supported by winsock.
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
/* \} */
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user