From cd25fb5f290ce9080a0e93908d40346c0607cbfe Mon Sep 17 00:00:00 2001 From: Blair McGlashan Date: Mon, 17 Sep 2018 20:58:33 +0100 Subject: [PATCH] Port fix for SmallInteger>>testModulo locking up in test runs # Conflicts: # Interprt.h # decode.cpp # objmem.cpp # process.cpp # thrdcall.cpp --- ExternalCall.asm | 8 ++- GCPrim.cpp | 4 ++ Interprt.h | 8 ++- interfac.cpp | 2 +- interprt.cpp | 6 ++ objmem.h | 45 +++++++------ process.cpp | 18 +++-- thrdcall.cpp | 172 ++++++++++++++++++++++++++++++----------------- thrdcall.h | 3 + 9 files changed, 175 insertions(+), 91 deletions(-) diff --git a/ExternalCall.asm b/ExternalCall.asm index 5e96522..bb539af 100644 --- a/ExternalCall.asm +++ b/ExternalCall.asm @@ -257,9 +257,13 @@ procAddressNotCached: test eax, eax ; Returns null if not a valid proc name jnz performCall + mov edx, callContext + ASSUME edx:PTR InterpRegisters add esp, 16 ; Remove args pushed for aborted call - PrimitiveFailureCode 1 - + mov edx, [edx].m_pActiveProcess + xor eax, eax + mov (Process PTR[edx]).m_primitiveFailureCode, SMALLINTONE + ret asyncDLL32Call ENDP getProcAddress PROC diff --git a/GCPrim.cpp b/GCPrim.cpp index 271801b..b2a2570 100644 --- a/GCPrim.cpp +++ b/GCPrim.cpp @@ -36,6 +36,7 @@ bool Interpreter::disableAsyncGC(bool bDisable) if (m_nOTOverflows > 0) { m_nOTOverflows = 0; + CHECKREFERENCES queueInterrupt(VMI_OTOVERFLOW, ObjectMemoryIntegerObjectOf(ObjectMemory::GetOTSize())); } return true; @@ -52,6 +53,7 @@ void Interpreter::NotifyOTOverflow() } else { + CHECKREFERENCES queueInterrupt(VMI_OTOVERFLOW, ObjectMemoryIntegerObjectOf(ObjectMemory::GetOTSize())); } } @@ -91,6 +93,8 @@ void Interpreter::asyncGC(DWORD gcFlags) // This has been usurped for GC primitive Oop* __fastcall Interpreter::primitiveCoreLeft(Oop* const sp , unsigned argCount) { + CHECKREFERENCESSP(sp); + DWORD gcFlags = 0; if (argCount) { diff --git a/Interprt.h b/Interprt.h index 89526bf..d763375 100644 --- a/Interprt.h +++ b/Interprt.h @@ -30,6 +30,7 @@ using namespace ST; #define TRACEARG(x) ,(x) #define TRACEPARM ,TRACEFLAG traceFlag #define TRACEDEFAULT TRACEPARM=TraceOff + #define CHECKREFERENCESSP(sp) Interpreter::checkReferences(sp) #define CHECKREFERENCES Interpreter::checkReferences(Interpreter::GetRegisters()); #define CHECKREFSNOFIX \ {\ @@ -43,6 +44,8 @@ using namespace ST; #define TRACEARG(x) #define TRACEDEFAULT #define CHECKREFERENCES + #define CHECKREFERENCESSP(sp) + #define CHECKREFERENCESIF(x) #define CHECKREFSNOFIX #endif @@ -91,6 +94,7 @@ class Interpreter static void RemoveVMReference(Oop); static void RemoveVMReference(OTE*); + static void checkReferences(Oop* const sp); static void checkReferences(InterpreterRegisters&); // Only needed for non-Debug because of C++ walkback code @@ -846,8 +850,8 @@ class Interpreter static int m_nFreeVMRef; static int m_nMaxVMRefs; // Current size of VM References array - enum { VMREFSINITIAL = 16 }; - enum { VMREFSGROWTH = 16 }; + enum { VMREFSINITIAL = 128 }; + enum { VMREFSGROWTH = 64 }; #endif }; diff --git a/interfac.cpp b/interfac.cpp index 3d09429..93ff97d 100755 --- a/interfac.cpp +++ b/interfac.cpp @@ -207,7 +207,7 @@ Oop __stdcall Interpreter::callback(SymbolOTE* selector, unsigned argCount TRACE //ASSERT(!memcmp(&savedContext, &m_registers, sizeof(InterpreterRegisters))); #endif - // Must countUp to prevent it being GC'd since the stack no longer has ref. count + // Must countUp to prevent it being GC'd since it is no longer ref'd from the stack VERIFY(retVal == popAndCountUp()); return retVal; } diff --git a/interprt.cpp b/interprt.cpp index 3c49127..4084623 100644 --- a/interprt.cpp +++ b/interprt.cpp @@ -299,6 +299,12 @@ static MWORD ResizeProcInContext(InterpreterRegisters& reg) return size; } +void Interpreter::checkReferences(Oop* const sp) +{ + m_registers.m_stackPointer = sp; + checkReferences(GetRegisters()); +} + // Check references without upsetting the current active process size (otherwise // this may mask bugs in the release version) void Interpreter::checkReferences(InterpreterRegisters& reg) diff --git a/objmem.h b/objmem.h index a148c6e..c2406c4 100755 --- a/objmem.h +++ b/objmem.h @@ -64,8 +64,8 @@ class ObjectMemory static Oop storePointerWithValue(Oop& oopSlot, Oop oopValue); static OTE* storePointerWithValue(OTE*& oteSlot, OTE* oteValue); static Oop storePointerWithValue(Oop& oopSlot, OTE* oteValue); - static Oop nilOutPointer(Oop& objectPointer); - static OTE* nilOutPointer(OTE*& ote); + static void nilOutPointer(Oop& objectPointer); + static void nilOutPointer(OTE*& ote); // Use these versions to store values which are not themselves ref. counted static Oop storePointerWithUnrefCntdValue(Oop&, Oop); @@ -188,6 +188,7 @@ class ObjectMemory #ifdef _DEBUG // Recalc and consistency check + static void checkReferences(Oop* const sp); static void checkReferences(); static void addRefsFrom(OTE* ote); static void checkPools(); @@ -681,30 +682,30 @@ inline Oop ObjectMemory::storePointerOfObjectWithValue(MWORD fieldIndex, Pointer // Useful for overwriting structure members inline Oop ObjectMemory::storePointerWithValue(Oop& oopSlot, Oop oopValue) { - // Sadly compiler refuses to inline the count up code, and macro seems to generate - // bad code(!) so inline by hand countUp(oopValue); // Increase the reference count on stored object - countDown(oopSlot); - return oopSlot = oopValue; + Oop oldValue = oopSlot; + oopSlot = oopValue; + countDown(oldValue); + return oopValue; } // Useful for overwriting structure members inline Oop ObjectMemory::storePointerWithUnrefCntdValue(Oop& oopSlot, Oop oopValue) { - // Sadly compiler refuses to inline the count up code, and macro seems to generate - // bad code(!) so inline by hand - countDown(oopSlot); - return oopSlot = oopValue; + Oop oldValue = oopSlot; + oopSlot = oopValue; + countDown(oldValue); + return oopValue; } // Useful for overwriting structure members inline OTE* ObjectMemory::storePointerWithValue(OTE*& oteSlot, OTE* oteValue) { - // Sadly compiler refuses to inline the count up code, and macro seems to generate - // bad code(!) so inline by hand oteValue->countUp(); // Increase the reference count on stored object - oteSlot->countDown(); - return (oteSlot = oteValue); + OTE* oteOldValue = oteSlot; + oteSlot = oteValue; + oteOldValue->countDown(); + return oteValue; } // Useful for overwriting structure members @@ -713,20 +714,24 @@ inline Oop ObjectMemory::storePointerWithValue(Oop& oopSlot, OTE* oteValue) // Sadly compiler refuses to inline the count up code, and macro seems to generate // bad code(!) so inline by hand oteValue->countUp(); // Increase the reference count on stored object - countDown(oopSlot); - return oopSlot = Oop(oteValue); + Oop oldValue = oopSlot; + oopSlot = reinterpret_cast(oteValue); + countDown(oldValue); + return oopSlot; } -inline Oop ObjectMemory::nilOutPointer(Oop& objectPointer) +inline void ObjectMemory::nilOutPointer(Oop& objectPointer) { + Oop oldValue = objectPointer; + objectPointer = reinterpret_cast(Pointers.Nil); countDown(objectPointer); - return objectPointer = Oop(Pointers.Nil); } -inline OTE* ObjectMemory::nilOutPointer(OTE*& ote) +inline void ObjectMemory::nilOutPointer(OTE*& ote) { + OTE* oldValue = ote; + ote = const_cast(Pointers.Nil); ote->countDown(); - return ote = const_cast(Pointers.Nil); } /////////////////////////////////////////////////////////////////////////////// diff --git a/process.cpp b/process.cpp index ada84b3..c697a35 100644 --- a/process.cpp +++ b/process.cpp @@ -1594,7 +1594,12 @@ Oop* __fastcall Interpreter::primitiveUnwindInterrupt(Oop* const) { // Terminate any overlapped call outstanding for the process, this may need to suspend the process // and so this may cause a context switch - TerminateOverlapped(actualActiveProcessPointer()); + ProcessOTE* oteActive = actualActiveProcessPointer(); + OverlappedCall* pOverlapped = oteActive->m_location->GetOverlappedCall(); + if (pOverlapped != nullptr && pOverlapped->IsInCall()) + { + TerminateOverlapped(oteActive); + } return primitiveSuccess(0); } @@ -1765,6 +1770,9 @@ bool Interpreter::TerminateOverlapped(ProcessOTE* oteProc) if (activeProcessPointer() == oteProc) Reschedule(); + + // The process must wait for the associated overlapped call thread to terminate + return true; } else { @@ -1774,12 +1782,10 @@ bool Interpreter::TerminateOverlapped(ProcessOTE* oteProc) HARDASSERT(FALSE); // Actually I don't think we can get here } - // The process was in/is in an overlapped call - return true; } - else - // The process is not in an overlapped call - return false; + + // The process can be terminated immediately + return false; } inline bool Process::SuspendOverlappedCall() diff --git a/thrdcall.cpp b/thrdcall.cpp index f687a11..1b168b8 100644 --- a/thrdcall.cpp +++ b/thrdcall.cpp @@ -64,8 +64,6 @@ inline void Process::SetThread(void* handle) // The overlapped thread has completed a call, return to the idle state void OverlappedCall::CallFinished() { - //beResting(); - // m_interpContext.m_oopMessageSelector = reinterpret_cast(Pointers.Nil); m_interpContext.m_oopNewMethod = reinterpret_cast(Pointers.Nil); m_nCallDepth--; } @@ -227,7 +225,7 @@ void OverlappedCall::compact() #if TRACING == 1 { TRACELOCK(); - TRACESTREAM << *this << " compacting " << m_oteProcess << endl; + TRACESTREAM << hex << GetCurrentThreadId() << "Compacting " << *this << endl; } #endif @@ -305,13 +303,12 @@ bool OverlappedCall::QueueForMe(PAPCFUNC pfnAPC) ostream& operator<<(ostream& stream, const OverlappedCall& oc) { - return stream << "OverlappedCall(" << &oc - << ", process: " << oc.m_oteProcess - << ", hThread: " << oc.m_hThread + return stream<< "OverlappedCall(" << &oc << ", id:" << oc.m_dwThreadId << ", state: " << oc.m_state << ", suspend:" << oc.m_nSuspendCount << ", calls:" << oc.m_nCallDepth + << ", process: " << oc.m_oteProcess #ifdef _DEBUG << ", refs: " << oc.m_dwRefs #endif @@ -330,14 +327,15 @@ OverlappedCall::OverlappedCall(ProcessOTE* oteProcess) : m_oteProcess(oteProcess), m_nSuspendCount(0), m_nCallDepth(0), m_state(OverlappedCall::Starting), - m_bCompletionRequestPending(false) + m_bCompletionRequestPending(false), + m_bCallPrimitiveFailed(false) { HARDASSERT(::GetCurrentThreadId() == Interpreter::MainThreadId()); #if TRACING == 1 { TRACELOCK(); - TRACESTREAM << m_dwThreadId << ": " << *this << " created" << endl; + TRACESTREAM << hex << GetCurrentThreadId() << ": Created " << *this << endl; } #endif @@ -356,7 +354,7 @@ OverlappedCall::~OverlappedCall() #if TRACING == 1 { TRACELOCK(); - TRACESTREAM << m_dwThreadId << ": " << *this << " destroyed" << endl; + TRACESTREAM << hex << GetCurrentThreadId() << ": Destroy " << *this << endl; } #endif @@ -437,7 +435,7 @@ DWORD OverlappedCall::WaitForRequest() #if TRACING == 1 { TRACELOCK(); - TRACESTREAM << m_dwThreadId << ": " << *this << "::Run() processed APCs while waiting" << endl; + TRACESTREAM << hex << GetCurrentThreadId() << ": Processed APCs while waiting for " << *this << endl; } #endif } @@ -457,8 +455,7 @@ int OverlappedCall::ProcessRequests() #if TRACING == 1 { TRACELOCK(); - TRACESTREAM << m_dwThreadId << ": Calling " << *this << " to " << *m_pMethod << - endl << " for " << m_oteProcess << endl; + TRACESTREAM << hex << GetCurrentThreadId() << ": Calling " << *m_pMethod << "; " << *this << endl; } #endif @@ -467,7 +464,7 @@ int OverlappedCall::ProcessRequests() #if TRACING == 1 { TRACELOCK(); - TRACESTREAM << hex << m_dwThreadId << ": Resting..." << endl; + TRACESTREAM << hex << GetCurrentThreadId() << ": Resting; " << m_dwThreadId << endl; } #endif } @@ -475,7 +472,7 @@ int OverlappedCall::ProcessRequests() #if TRACING == 1 { TRACELOCK(); - TRACESTREAM << hex << *this << " exiting on " << dwRet << endl; + TRACESTREAM << hex << GetCurrentThreadId() << ": Exiting (" << dwRet << L"); " << m_dwThreadId << endl; } #endif @@ -494,27 +491,35 @@ void OverlappedCall::PerformCall() HARDASSERT(m_oteProcess->m_location->Thread() == this); - #if TRACING == 1 - { - TRACELOCK(); - TRACESTREAM << hex << m_dwThreadId << ": " << *this << " to " << *m_pMethod << " completes." << endl; - } - #endif - - InterpreterRegisters& regs = Interpreter::GetRegisters(); - ASSERT(m_interpContext.m_pActiveProcess == regs.m_pActiveProcess); - if (retVal != NULL) { + #if TRACING == 1 + { + TRACELOCK(); + TRACESTREAM << hex << GetCurrentThreadId() << ": Completed " << *m_pMethod << "; " << *this << endl; + } + #endif + + InterpreterRegisters& regs = Interpreter::GetRegisters(); + ASSERT(m_interpContext.m_pActiveProcess == regs.m_pActiveProcess); regs.StoreSPInFrame(); } else { - // The call failed as if it were a primitive failure - the args have - // not been popped and we need to activate the backup smalltalk code + #if TRACING == 1 + { + TRACELOCK(); + TRACESTREAM << hex << GetCurrentThreadId() << ": Call failed; " << GetLastErrorText() << endl; + } + #endif - Interpreter::activateNewMethod(m_interpContext.m_oopNewMethod->m_location); - regs.PrepareToSuspendProcess(); + // The call failed as if it were a primitive failure - the args have + // not been popped and we need to activate the backup smalltalk code. + // However, since the calling Process is in a wait state, we need to + // notify the main thread to wake it up + m_bCallPrimitiveFailed = true; + NotifyInterpreterOfCallReturn(); + WaitForInterpreter(); } #ifdef _DEBUG @@ -535,7 +540,7 @@ bool OverlappedCall::Initiate(CompiledMethod* pMethod, unsigned argCount) #if TRACING == 1 { TRACELOCK(); - TRACESTREAM << hex << GetCurrentThreadId() << ": " << *this << "::Initiate (main thread part)" << endl; + TRACESTREAM << hex << GetCurrentThreadId() << ": Initiate; " << *this << endl; } #endif @@ -616,8 +621,19 @@ void OverlappedCall::OnActivateProcess() { m_bCompletionRequestPending = false; + if (m_bCallPrimitiveFailed) + { + m_bCallPrimitiveFailed = false; + + ASSERT(m_interpContext.m_stackPointer == Interpreter::m_registers.m_stackPointer); + ASSERT(m_interpContext.m_basePointer == Interpreter::m_registers.m_basePointer); + Interpreter::m_registers.m_oopNewMethod = m_interpContext.m_oopNewMethod; + Interpreter::activateNewMethod(m_interpContext.m_oopNewMethod->m_location); + } + // Let the overlapped thread continue ::SetEvent(m_hEvtGo); + // And wait for it to finish (non-alertable since we don't want other completions to interfere) DWORD dwRet = ::WaitForSingleObject(m_hEvtCompleted, INFINITE); if (dwRet != WAIT_OBJECT_0) @@ -648,7 +664,7 @@ bool OverlappedCall::QueueTerminate() #if TRACING == 1 { TRACELOCK(); - TRACESTREAM << hex << GetCurrentThreadId() << ": " << *this << "::QueueTerminate" << endl; + TRACESTREAM << hex << GetCurrentThreadId()<< ": Queue terminate; " << *this << endl; } #endif @@ -677,8 +693,8 @@ void __stdcall OverlappedCall::SuspendAPC(DWORD dwParam) #if TRACING == 1 { - tracelock lock(pThis->thinDump); - pThis->thinDump << hex << GetCurrentThreadId() << ": SuspendAPC(" << *pThis << ")" << endl; + CAutoLock lock(pThis->thinDump); + pThis->thinDump << hex << GetCurrentThreadId()<< ": SuspendAPC; " << *pThis << endl; } #endif @@ -706,7 +722,7 @@ bool OverlappedCall::QueueSuspend() #if TRACING == 1 { TRACELOCK(); - TRACESTREAM << hex << GetCurrentThreadId() << ": " << *this << "::SuspendThread()" << endl; + TRACESTREAM << hex << GetCurrentThreadId()<< ": Queue suspend; " << *this << endl; } #endif @@ -720,7 +736,7 @@ DWORD OverlappedCall::Resume() #if TRACING == 1 { tracelock lock(::thinDump); - ::thinDump << hex << GetCurrentThreadId() << ": " << *this << "::ResumeThread()" << endl; + ::thinDump << hex << GetCurrentThreadId()<< ": " << *this<< "::ResumeThread()" << endl; } #endif InterlockedDecrement(&m_nSuspendCount); @@ -741,12 +757,12 @@ void OverlappedCall::SuspendThread() dwRet; #if TRACING == 1 TRACELOCK(); - TRACESTREAM << hex << GetCurrentThreadId() << ": " << *this << "::SuspendThread() Suspend count is " << dwRet << endl; + TRACESTREAM << hex << GetCurrentThreadId()<< ": Suspending (count=" << m_nSuspendCount << "); " << *this << dwRet << endl; } else { TRACELOCK(); - TRACESTREAM << hex << GetCurrentThreadId() << ": " << *this << "::SuspendThread() ignored as suspend count <= 0" << endl; + TRACESTREAM << hex << GetCurrentThreadId()<< ": Suspend ignored (count=" << m_nSuspendCount << "); " << *this << endl; #endif } } @@ -759,19 +775,50 @@ DWORD OverlappedCall::ResumeThread() /////////////////////////////////////////////////////////////////////////////// // Thread main function +int OverlappedCall::MainExceptionFilter(LPEXCEPTION_POINTERS pExInfo) +{ + switch (pExInfo->ExceptionRecord->ExceptionCode) + { + case SE_VMTERMINATETHREAD: + return EXCEPTION_EXECUTE_HANDLER; + + case EXCEPTION_FLT_STACK_CHECK: + case EXCEPTION_INT_DIVIDE_BY_ZERO: + case EXCEPTION_ACCESS_VIOLATION: + case SE_VMCRTFAULT: + return EXCEPTION_EXECUTE_HANDLER; + } + + return EXCEPTION_CONTINUE_SEARCH; +} + +static void __cdecl InvalidCrtParameterHandler( + wchar_t const* expression, + wchar_t const* function, + wchar_t const* file, + unsigned int line, + uintptr_t pReservered +) +{ + TRACE("%x: CRT parameter fault in '%s' of %s, %s(%u)", GetCurrentThreadId(), expression, function, file, line); + TODO("Raise an exception and report the error in a similar way to the main VM thread"); + return; +} + int OverlappedCall::TryMain() { int ret; __try { + _set_thread_local_invalid_parameter_handler(InvalidCrtParameterHandler); ret = Main(); } - __except(GetExceptionCode() == SE_VMTERMINATETHREAD ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) + __except(MainExceptionFilter(GetExceptionInformation())) { #if TRACING == 1 { TRACELOCK(); - TRACESTREAM << hex << GetCurrentThreadId() << ": " << *this << " received terminate exception" << endl; + TRACESTREAM << hex << GetCurrentThreadId()<< ": Terminating; " << *this << endl; } #endif @@ -836,8 +883,8 @@ void __stdcall OverlappedCall::TerminatedAPC(DWORD dwParam) #if TRACING == 1 { - tracelock lock(pThis->thinDump); - pThis->thinDump << hex << GetCurrentThreadId() << ": TerminatedAPC(" << *pThis << ")" << endl; + CAutoLock lock(pThis->thinDump); + pThis->thinDump << hex << GetCurrentThreadId()<< ": TerminatedAPC; " << *pThis << endl; } #endif @@ -856,8 +903,8 @@ void OverlappedCall::RemoveFromPendingTerminations() HARDASSERT(myProc->Thread() == this); myProc->ClearThread(); - // Return it to the scheduling queues - Interpreter::sleep(oteProc); + // Return it to the scheduling queues - we resume it to cause a scheduling decision to be made. + Interpreter::resume(oteProc); // Remove the reference that was from the pending terminations list oteProc->countDown(); } @@ -894,6 +941,24 @@ void OverlappedCall::NotifyInterpreterOfCallReturn() Interpreter::SetWakeupEvent(); } +void OverlappedCall::WaitForInterpreter() +{ + // Wait for main thread to process the async signal and permit us to continue + DWORD dwRet; + while ((dwRet = ::WaitForSingleObjectEx(m_hEvtGo, 5000, TRUE)) != WAIT_OBJECT_0) + { + thinDump << hex << GetCurrentThreadId() << ": OnCallReturned, wait interrupted (" << dwRet << "); " << *this << endl; + if (dwRet == WAIT_ABANDONED) + { + // Event deleted, etc, so terminate the thread + RaiseException(SE_VMTERMINATETHREAD, EXCEPTION_NONCONTINUABLE, 0, NULL); + } + + // Interrupted to process an APC (probably a suspend/terminate) or due to a timeout + HARDASSERT(dwRet == WAIT_IO_COMPLETION || dwRet == WAIT_TIMEOUT); + } +} + /////////////////////////////////////////////////////////////////////////////// // The call on the worker thread has returned to the assembler call primitive. // We can't complete the call until the main thread is ready to accept it, so @@ -910,26 +975,13 @@ void OverlappedCall::OnCallReturned() #if TRACING == 1 { TRACELOCK(); - TRACESTREAM << hex << GetCurrentThreadId() << ": " << *this << "::OnCallReturned() waiting to complete" << endl; + TRACESTREAM << hex << GetCurrentThreadId() << ": OnCallReturned, waiting to complete; " << *this << endl; } #endif //if (inPrim) DebugBreak(); - // Wait for main thread to process the async signal and permit us to continue - DWORD dwRet; - while ((dwRet = ::WaitForSingleObjectEx(m_hEvtGo, 5000, TRUE)) != WAIT_OBJECT_0) - { - thinDump << hex << GetCurrentThreadId() << ": " << *this << "::OnCallReturned() wait interrupted with " << dwRet << endl; - if (dwRet == WAIT_ABANDONED) - { - // Event deleted, etc, so terminate the thread - RaiseException(SE_VMTERMINATETHREAD, EXCEPTION_NONCONTINUABLE, 0, NULL); - } - - // Interrupted to process an APC (probably a suspend/terminate) or due to a timeout - HARDASSERT(dwRet == WAIT_IO_COMPLETION || dwRet == WAIT_TIMEOUT); - } + WaitForInterpreter(); if (GetProcess()->Thread() != this || m_state != Running) { @@ -944,7 +996,7 @@ void OverlappedCall::OnCallReturned() #if TRACING == 1 { TRACELOCK(); - TRACESTREAM << hex << GetCurrentThreadId() << ": " << *this << "::OnCallReturned() Completing... " << endl; + TRACESTREAM << hex << GetCurrentThreadId() << ": OnCallReturned, completing; " << *this << endl; } #endif @@ -1016,7 +1068,7 @@ Oop* __fastcall Interpreter::primitiveAsyncDLL32Call(void*, unsigned argCount) #if TRACING == 1 { TRACELOCK(); - TRACESTREAM << "primAsync32: Prepare to call " << method << endl; + TRACESTREAM << "primAsync32: Prepare to call " << *method << " from " << Interpreter::actualActiveProcessPointer() << endl; } #endif @@ -1040,7 +1092,7 @@ Oop* __fastcall Interpreter::primitiveAsyncDLL32Call(void*, unsigned argCount) #if TRACING == 1 { TRACELOCK(); - TRACESTREAM << "registers.sp = " << m_registers.m_stackPointer << " frame.sp = " << + TRACESTREAM << "registers.sp = " << m_registers.m_stackPointer<< " frame.sp = " << m_registers.m_pActiveFrame->stackPointer() << endl; } #endif diff --git a/thrdcall.h b/thrdcall.h index fe7b109..3e44a73 100755 --- a/thrdcall.h +++ b/thrdcall.h @@ -225,6 +225,7 @@ class OverlappedCall : public DoubleLink // Queue a notification to the interpreter thread that an overlapped thread // has received a termination signal bool NotifyInterpreterOfTermination(); + void WaitForInterpreter(); void RemoveFromPendingTerminations(); @@ -263,6 +264,7 @@ class OverlappedCall : public DoubleLink // Thread entry point function static unsigned __stdcall ThreadMain(void* pThis); + static int MainExceptionFilter(LPEXCEPTION_POINTERS pExInfo); // APC functions (APCs are used to queue messages between threads) static void __stdcall SuspendAPC(DWORD dwParam); @@ -311,6 +313,7 @@ class OverlappedCall : public DoubleLink private: SHAREDLONG m_nSuspendCount; bool m_bCompletionRequestPending; + bool m_bCallPrimitiveFailed; };