summaryrefslogtreecommitdiff
path: root/src/vm/appdomain.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/appdomain.cpp')
-rw-r--r--src/vm/appdomain.cpp290
1 files changed, 0 insertions, 290 deletions
diff --git a/src/vm/appdomain.cpp b/src/vm/appdomain.cpp
index 563de46075..6aff6ab60a 100644
--- a/src/vm/appdomain.cpp
+++ b/src/vm/appdomain.cpp
@@ -95,8 +95,6 @@ static const WCHAR OTHER_DOMAIN_FRIENDLY_NAME_PREFIX[] = W("Domain");
#define STATIC_OBJECT_TABLE_BUCKET_SIZE 1020
-//#define _DEBUG_ADUNLOAD 1
-
// Statics
SPTR_IMPL(AppDomain, AppDomain, m_pTheAppDomain);
@@ -6634,225 +6632,12 @@ void AppDomain::ExceptionUnwind(Frame *pFrame)
CONTRACTL_END;
LOG((LF_APPDOMAIN, LL_INFO10, "AppDomain::ExceptionUnwind for %8.8x\n", pFrame));
-#if _DEBUG_ADUNLOAD
- printf("%x AppDomain::ExceptionUnwind for %8.8p\n", GetThread()->GetThreadId(), pFrame);
-#endif
Thread *pThread = GetThread();
_ASSERTE(pThread);
LOG((LF_APPDOMAIN, LL_INFO10, "AppDomain::ExceptionUnwind: not first transition or abort\n"));
}
-BOOL AppDomain::StopEEAndUnwindThreads(unsigned int retryCount, BOOL *pFMarkUnloadRequestThread)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- Thread *pThread = NULL;
- DWORD nThreadsNeedMoreWork=0;
- if (retryCount != (unsigned int)-1 && retryCount < g_pConfig->AppDomainUnloadRetryCount())
- {
- Thread *pCurThread = GetThread();
- if (pCurThread->CatchAtSafePoint())
- pCurThread->PulseGCMode();
-
- m_dwThreadsStillInAppDomain=nThreadsNeedMoreWork;
- return !nThreadsNeedMoreWork;
- }
-
- // For now piggyback on the GC's suspend EE mechanism
- ThreadSuspend::SuspendEE(ThreadSuspend::SUSPEND_FOR_APPDOMAIN_SHUTDOWN);
-#ifdef _DEBUG
- // <TODO>@todo: what to do with any threads that didn't stop?</TODO>
- _ASSERTE(ThreadStore::s_pThreadStore->DbgBackgroundThreadCount() > 0);
-#endif // _DEBUG
-
- int totalADCount = 0;
- int finalizerADCount = 0;
- pThread = NULL;
-
- RuntimeExceptionKind reKind = kLastException;
- UINT resId = 0;
- SmallStackSString ssThreadId;
-
- while ((pThread = ThreadStore::GetThreadList(pThread)) != NULL)
- {
- // we already checked that we're not running in the unload domain
- if (pThread == GetThread())
- {
- continue;
- }
-
-#ifdef _DEBUG
- void PrintStackTraceWithADToLog(Thread *pThread);
- if (LoggingOn(LF_APPDOMAIN, LL_INFO100)) {
- LOG((LF_APPDOMAIN, LL_INFO100, "\nStackTrace for %x\n", pThread->GetThreadId()));
- PrintStackTraceWithADToLog(pThread);
- }
-#endif // _DEBUG
- int count = 0;
- Frame *pFrame = pThread->GetFirstTransitionInto(this, &count);
- if (! pFrame) {
- _ASSERTE(count == 0);
- continue;
- }
-
- if (pThread != FinalizerThread::GetFinalizerThread())
- {
- totalADCount += count;
- nThreadsNeedMoreWork++;
- }
- else
- {
- finalizerADCount = count;
- }
-
- // don't setup the exception info for the unloading thread unless it's the last one in
- if (retryCount != ((unsigned int) -1) && retryCount > g_pConfig->AppDomainUnloadRetryCount() && reKind == kLastException)
- {
-#ifdef AD_BREAK_ON_CANNOT_UNLOAD
- static int breakOnCannotUnload = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_ADBreakOnCannotUnload);
- if (breakOnCannotUnload)
- _ASSERTE(!"Cannot unload AD");
-#endif // AD_BREAK_ON_CANNOT_UNLOAD
- reKind = kCannotUnloadAppDomainException;
- resId = IDS_EE_ADUNLOAD_CANT_UNWIND_THREAD;
- ssThreadId.Printf(W("%x"), pThread->GetThreadId());
- STRESS_LOG2(LF_APPDOMAIN, LL_INFO10, "AppDomain::UnwindThreads cannot stop thread %x with %d transitions\n", pThread->GetThreadId(), count);
- // don't break out of this early or the assert totalADCount == (int)m_dwThreadEnterCount below will fire
- // it's better to chew a little extra time here and make sure our counts are consistent
- }
- // only abort the thread requesting the unload if it's the last one in, that way it will get
- // notification that the unload failed for some other thread not being aborted. And don't abort
- // the finalizer thread - let it finish it's work as it's allowed to be in there. If it won't finish,
- // then we will eventually get a CannotUnloadException on it.
-
- if (pThread != FinalizerThread::GetFinalizerThread())
- {
-
- STRESS_LOG2(LF_APPDOMAIN, LL_INFO100, "AppDomain::UnwindThreads stopping %x with %d transitions\n", pThread->GetThreadId(), count);
- LOG((LF_APPDOMAIN, LL_INFO100, "AppDomain::UnwindThreads stopping %x with %d transitions\n", pThread->GetThreadId(), count));
-#if _DEBUG_ADUNLOAD
- printf("AppDomain::UnwindThreads %x stopping %x with first frame %8.8p\n", GetThread()->GetThreadId(), pThread->GetThreadId(), pFrame);
-#endif
- pThread->SetAbortRequest(EEPolicy::TA_Safe);
- }
- TESTHOOKCALL(UnwindingThreads(GetId().m_dwId)) ;
- }
- _ASSERTE(totalADCount + finalizerADCount == (int)m_dwThreadEnterCount);
-
- //@TODO: This is intended to catch a stress bug. Remove when no longer needed.
- if (totalADCount + finalizerADCount != (int)m_dwThreadEnterCount)
- FreeBuildDebugBreak();
-
- // if our count did get messed up, set it to whatever count we actually found in the domain to avoid looping
- // or other problems related to incorrect count. This is very much a bug if this happens - a thread should always
- // exit the domain gracefully.
- // m_dwThreadEnterCount = totalADCount;
-
- // CommonTripThread will handle the abort for any threads that we've marked
- ThreadSuspend::RestartEE(FALSE, TRUE);
- if (reKind != kLastException)
- COMPlusThrow(reKind, resId, ssThreadId.GetUnicode());
-
- _ASSERTE((totalADCount==0 && nThreadsNeedMoreWork==0) ||(totalADCount!=0 && nThreadsNeedMoreWork!=0));
-
- m_dwThreadsStillInAppDomain=nThreadsNeedMoreWork;
- return (totalADCount == 0);
-}
-
-void AppDomain::UnwindThreads()
-{
- // This function should guarantee appdomain
- // consistency even if it fails. Everything that is going
- // to make the appdomain impossible to reenter
- // should be factored out
-
- // <TODO>@todo: need real synchronization here!!!</TODO>
- CONTRACTL
- {
- MODE_COOPERATIVE;
- THROWS;
- GC_TRIGGERS;
- }
- CONTRACTL_END;
-
- int retryCount = -1;
- m_dwThreadsStillInAppDomain=(ULONG)-1;
- ULONGLONG startTime = CLRGetTickCount64();
-
- // Force threads to go through slow path during AD unload.
- TSSuspendHolder shTrap;
-
- BOOL fMarkUnloadRequestThread = TRUE;
-
- // now wait for all the threads running in our AD to get out
- do
- {
- DWORD timeout = GetEEPolicy()->GetTimeout(OPR_AppDomainUnload);
- EPolicyAction action = GetEEPolicy()->GetActionOnTimeout(OPR_AppDomainUnload, NULL);
- if (timeout != INFINITE && action >= eExitProcess) {
- // Escalation policy specified.
- ULONGLONG curTime = CLRGetTickCount64();
- ULONGLONG elapseTime = curTime - startTime;
- if (elapseTime > timeout)
- {
- // Escalate
- switch (action)
- {
- case eExitProcess:
- case eFastExitProcess:
- case eRudeExitProcess:
- case eDisableRuntime:
- GetEEPolicy()->NotifyHostOnTimeout(OPR_AppDomainUnload, action);
- EEPolicy::HandleExitProcessFromEscalation(action, HOST_E_EXITPROCESS_TIMEOUT);
- _ASSERTE (!"Should not reach here");
- break;
- default:
- break;
- }
- }
- }
-#ifdef _DEBUG
- if (LoggingOn(LF_APPDOMAIN, LL_INFO100))
- DumpADThreadTrack();
-#endif // _DEBUG
- if (StopEEAndUnwindThreads(retryCount, &fMarkUnloadRequestThread))
- break;
- if (timeout != INFINITE)
- {
- // Turn off the timeout used by AD.
- retryCount = 1;
- }
- else
- {
- // GCStress takes a long time to unwind, due to expensive creation of
- // a threadabort exception.
- if (!GCStress<cfg_any>::IsEnabled())
- ++retryCount;
- LOG((LF_APPDOMAIN, LL_INFO10, "AppDomain::UnwindThreads iteration %d waiting on thread count %d\n", retryCount, m_dwThreadEnterCount));
-#if _DEBUG_ADUNLOAD
- printf("AppDomain::UnwindThreads iteration %d waiting on thread count %d\n", retryCount, m_dwThreadEnterCount);
-#endif
- }
-
- if (m_dwThreadEnterCount != 0)
- {
-#ifdef _DEBUG
- GetThread()->UserSleep(20);
-#else // !_DEBUG
- GetThread()->UserSleep(10);
-#endif // !_DEBUG
- }
- }
- while (TRUE) ;
-}
-
#ifdef _DEBUG
void AppDomain::TrackADThreadEnter(Thread *pThread, Frame *pFrame)
@@ -7506,81 +7291,6 @@ ULONGLONG g_ObjFinalizeStartTime = 0;
Volatile<BOOL> g_FinalizerIsRunning = FALSE;
Volatile<ULONG> g_FinalizerLoopCount = 0;
-ULONGLONG GetObjFinalizeStartTime()
-{
- LIMITED_METHOD_CONTRACT;
- return g_ObjFinalizeStartTime;
-}
-
-void FinalizerThreadAbortOnTimeout()
-{
- STATIC_CONTRACT_NOTHROW;
- STATIC_CONTRACT_MODE_COOPERATIVE;
- STATIC_CONTRACT_GC_TRIGGERS;
-
- {
- // If finalizer thread is blocked because scheduler is running another task,
- // or it is waiting for another thread, we first see if we get finalizer thread
- // running again.
- Thread::ThreadAbortWatchDog();
- }
-
- EX_TRY
- {
- Thread *pFinalizerThread = FinalizerThread::GetFinalizerThread();
- EPolicyAction action = GetEEPolicy()->GetActionOnTimeout(OPR_FinalizerRun, pFinalizerThread);
- switch (action)
- {
- case eAbortThread:
- GetEEPolicy()->NotifyHostOnTimeout(OPR_FinalizerRun, action);
- pFinalizerThread->UserAbort(Thread::TAR_Thread,
- EEPolicy::TA_Safe,
- INFINITE,
- Thread::UAC_FinalizerTimeout);
- break;
- case eRudeAbortThread:
- GetEEPolicy()->NotifyHostOnTimeout(OPR_FinalizerRun, action);
- pFinalizerThread->UserAbort(Thread::TAR_Thread,
- EEPolicy::TA_Rude,
- INFINITE,
- Thread::UAC_FinalizerTimeout);
- break;
- case eUnloadAppDomain:
- {
- AppDomain *pDomain = pFinalizerThread->GetDomain();
- pFinalizerThread->UserAbort(Thread::TAR_Thread,
- EEPolicy::TA_Safe,
- INFINITE,
- Thread::UAC_FinalizerTimeout);
- }
- break;
- case eRudeUnloadAppDomain:
- {
- AppDomain *pDomain = pFinalizerThread->GetDomain();
- pFinalizerThread->UserAbort(Thread::TAR_Thread,
- EEPolicy::TA_Rude,
- INFINITE,
- Thread::UAC_FinalizerTimeout);
- }
- break;
- case eExitProcess:
- case eFastExitProcess:
- case eRudeExitProcess:
- case eDisableRuntime:
- GetEEPolicy()->NotifyHostOnTimeout(OPR_FinalizerRun, action);
- EEPolicy::HandleExitProcessFromEscalation(action, HOST_E_EXITPROCESS_TIMEOUT);
- _ASSERTE (!"Should not get here");
- break;
- default:
- break;
- }
- }
- EX_CATCH
- {
- }
- EX_END_CATCH(SwallowAllExceptions);
-}
-
enum WorkType
{
WT_UnloadDomain = 0x1,